001: //** Copyright Statement ***************************************************
002: //The Salmon Open Framework for Internet Applications (SOFIA)
003: // Copyright (C) 1999 - 2002, Salmon LLC
004: //
005: // This program is free software; you can redistribute it and/or
006: // modify it under the terms of the GNU General Public License version 2
007: // as published by the Free Software Foundation;
008: //
009: // This program is distributed in the hope that it will be useful,
010: // but WITHOUT ANY WARRANTY; without even the implied warranty of
011: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: // GNU General Public License for more details.
013: //
014: // You should have received a copy of the GNU General Public License
015: // along with this program; if not, write to the Free Software
016: // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
017: //
018: // For more information please visit http://www.salmonllc.com
019: //** End Copyright Statement ***************************************************
020: package com.salmonllc.jsp;
021:
022: import java.sql.SQLException;
023: import java.util.Enumeration;
024:
025: import com.salmonllc.html.*;
026: import com.salmonllc.html.events.SubmitEvent;
027: import com.salmonllc.html.events.SubmitListener;
028: import com.salmonllc.html.events.ValueChangedListener;
029: import com.salmonllc.html.events.ValueChangedEvent;
030: import com.salmonllc.localizer.LanguagePreferences;
031: import com.salmonllc.localizer.LanguageResourceFinder;
032: import com.salmonllc.properties.Props;
033: import com.salmonllc.sql.DataStoreException;
034: import com.salmonllc.sql.QBEBuilder;
035: import com.salmonllc.sql.DataStoreBuffer;
036:
037: /**
038: * An extended version of the display box with addional functionality for building search forms
039: *
040: */
041: public class JspSearchFormDisplayBox extends JspFormDisplayBox
042: implements SubmitListener {
043:
044: private QBEBuilder _criteriaBuilder;
045:
046: private String _criteriaBuilderName, _criteriaValidatorName,
047: _listFormName;
048: private HtmlSubmitButton _searchButton, _addButton,
049: _cancelLookupButton;
050: private JspListFormDisplayBox _listForm;
051: private String _searchButtonAccessKey, _addButtonAccessKey,
052: _searchButtonCaption, _addButtonCaption,
053: _cancelLookupAccessKey, _cancelLookupButtonCaption;
054: private String _dataModifiedQuestion = "Data has been modified, and doing a new search will cause the changes to be lost. Continue? ";
055: private HtmlContainer _okCancelButtons;
056: private HtmlSubmitButton _okButton, _cancelButton;
057: private boolean _cancelLookupButtonVisible = true;
058: private HtmlHiddenField _dataModifiedValue;
059:
060: public JspSearchFormDisplayBox(String name, HtmlPage page) {
061: this (name, null, page);
062: }
063:
064: public void trySearch() {
065: if (_listForm != null && _listForm.isDataModified())
066: if (_validator.getUseAlertsForErrors()) {
067: addConfirmScript(_dataModifiedQuestion,
068: _dataModifiedValue);
069: } else {
070: _validator.setErrorMessage(_dataModifiedQuestion, null,
071: -1, _okCancelButtons);
072: }
073: else
074: try {
075: doSearch();
076: } catch (Exception e1) {
077: _validator.setErrorMessage(e1.getMessage());
078: }
079: }
080:
081: private class SearchAction implements SubmitListener,
082: ValueChangedListener {
083: public boolean submitPerformed(SubmitEvent e) throws Exception {
084: try {
085: doSearch();
086: } catch (Exception e1) {
087: _validator.setErrorMessage(e1.getMessage());
088: }
089: return true;
090: }
091:
092: public boolean valueChanged(ValueChangedEvent e)
093: throws Exception {
094: if (_dataModifiedValue.getValue() != null
095: && _dataModifiedValue.getValue().equals("1")) {
096: doSearch();
097: }
098: return true;
099: }
100: }
101:
102: public JspSearchFormDisplayBox(String name, String theme,
103: HtmlPage page) {
104: super (name, theme, page);
105:
106: _searchButton = new HtmlSubmitButton(name + "searchButton",
107: "Search", theme, page);
108: _addButton = new HtmlSubmitButton(name + "addButton", "Add",
109: theme, page);
110: _searchButton.addSubmitListener(this );
111: _cancelLookupButton = new HtmlSubmitButton(name
112: + "cancelButton", "Cancel", theme, page);
113: _addButton.addSubmitListener(this );
114: _cancelLookupButton.addSubmitListener(this );
115: _buttons.add(_searchButton);
116: _buttons.add(_addButton);
117: _buttons.add(_cancelLookupButton);
118: add(_searchButton, TYPE_COMP);
119: add(_addButton, TYPE_COMP);
120: add(_cancelLookupButton, TYPE_COMP);
121: setUpButtons();
122:
123: SearchAction searchAction = new SearchAction();
124: _okCancelButtons = new HtmlContainer("sfokcancelquestion", page);
125: _okCancelButtons.add(_okButton = new MessageButton(getPage(),
126: "dataModifiedOK", _okButtonCap, searchAction));
127: _okCancelButtons
128: .add(_cancelButton = new MessageButton(getPage(),
129: "dataModifiedCancel", _cancelButtonCap, null));
130: _messageButtons.add(_okButton);
131: _messageButtons.add(_cancelButton);
132: _cancelLookupButton.setVisible(false);
133:
134: _dataModifiedValue = new HtmlHiddenField("jsdatamodifiedvalue",
135: "0", page);
136: _dataModifiedValue.addValueChangedListener(searchAction);
137: add(_dataModifiedValue, TYPE_COMP);
138: _hidden.add(_dataModifiedValue);
139: }
140:
141: /**
142: *Called by the tag handler to set the name of the QBEBuilder. The autoBindComponents will lookup the name of the component and attach it to this one or try to discover it if the name is null
143: */
144: public void setQBEBuilderName(String name) {
145: _criteriaBuilderName = name;
146: }
147:
148: /**
149: *Called by the tag handler to set the name of the QBEValidator. The autoBindComponents will lookup the name of the component and attach it to this one or try to discover it if the name is null
150: */
151: public void setQBEValidatorName(String name) {
152: _criteriaValidatorName = name;
153: }
154:
155: /**
156: *Called by the tag handler to set the name of the ListForm. The autoBindComponents will lookup the name of the component and attach it to this one or try to discover it if the name is null
157: */
158: public void setListFormName(String name) {
159: _listFormName = name;
160: }
161:
162: /**
163: * Binds various components to the component based on their names passed to the constructor. CriteriaBuilder, CriteriaValidator and ListForm. This method is called by the framework and should not be called directly.
164: */
165: public void autoBindComponents() {
166: JspController cont = (JspController) getPage();
167:
168: if (_criteriaBuilderName != null)
169: _criteriaBuilder = (QBEBuilder) cont.getDataSource(_criteriaBuilderName);
170: else {
171: //find the first QBEBuilder in the page
172: Enumeration enum = cont.getDataSources();
173: while (enum.hasMoreElements()) {
174: Object o = enum.nextElement();
175: if (o instanceof QBEBuilder) {
176: _criteriaBuilder = (QBEBuilder) o;
177: break;
178: }
179: }
180: }
181: if (_criteriaValidatorName != null)
182: _validator = (HtmlValidatorText) cont.getComponent(_criteriaValidatorName);
183: else {
184: //see if there is a validator for this qbebuilder
185: Enumeration enum = cont.getComponents();
186: while (enum.hasMoreElements()) {
187: Object o = enum.nextElement();
188: if (o instanceof HtmlValidatorText) {
189: HtmlValidatorText test = (HtmlValidatorText) o;
190: if (test.getDataStore() == _criteriaBuilder) {
191: _validator = test;
192: break;
193: }
194: }
195: }
196: }
197: if (_validator == null && _criteriaBuilder != null) {
198: boolean hasRules = false;
199: for (int i = 0; i < _criteriaBuilder.getColumnCount(); i++) {
200: if (_criteriaBuilder.getValidationRulesForColumn(i) != null) {
201: hasRules = true;
202: break;
203: }
204: }
205: if (hasRules) {
206: _validator = new HtmlValidatorText(getName() + "validator", cont);
207: _validator.setBreaksBefore(0);
208: _validator.setBreaksAfter(2);
209: _validator.setDataStore(_criteriaBuilder);
210: _validator.importRules(_criteriaBuilder);
211: _validatorBuiltInternally = true;
212: add(_validator, TYPE_COMP);
213: }
214: }
215:
216: if (_validator != null)
217: _validator.addSubmitToListenTo(_searchButton);
218: else {
219: _validator = new HtmlValidatorText(getName() + "validator", cont);
220: _validator.setBreaksBefore(0);
221: _validator.setBreaksAfter(2);
222: _validatorBuiltInternally = true;
223: add(_validator, TYPE_COMP);
224: }
225:
226: if (_listFormName != null)
227: _listForm = (JspListFormDisplayBox) cont.getComponent(_listFormName);
228: else {
229: Enumeration enum = cont.getComponents();
230: while (enum.hasMoreElements()) {
231: Object o = enum.nextElement();
232: if (o instanceof JspListFormDisplayBox) {
233: _listForm = (JspListFormDisplayBox) o;
234: break;
235: }
236: }
237: }
238: }
239:
240: /**
241: * Sets the search button visible or not
242: */
243: public void setSearchButtonVisible(boolean visible) {
244: _searchButton.setVisible(visible);
245: }
246:
247: /**
248: * Sets the text to display on the search button
249: */
250: public void setSearchButtonCaption(String caption) {
251: _searchButton.setDisplayName(caption);
252: }
253:
254: /**
255: * Sets the add button visible or not
256: */
257: public void setAddButtonVisible(boolean visible) {
258: _addButton.setVisible(visible);
259: }
260:
261: /**
262: * Sets the add button visible or not
263: */
264: public void setAddButtonCaption(String caption) {
265: _addButton.setDisplayName(caption);
266: }
267:
268: /**
269: * Returns the search button visible or not
270: */
271: public boolean isSearchButtonVisible() {
272: return _searchButton.getVisible();
273: }
274:
275: /**
276: * Returns the text to display on the search button
277: */
278: public String getSearchButtonCaption() {
279: return _searchButton.getDisplayName();
280: }
281:
282: /**
283: * Return the add button visible or not
284: */
285: public boolean isAddButtonVisible() {
286: return _addButton.getVisible();
287: }
288:
289: /**
290: * Returns the add button visible or not
291: */
292: public String getAddButtonCaption() {
293: return _addButton.getDisplayName();
294: }
295:
296: /**
297: * Returns the font style for the search and add buttons
298: */
299: public String getButtonFontStyle() {
300: return _searchButton.getButtonFontStyle();
301: }
302:
303: /**
304: * Returns the background color for the search and add buttons
305: */
306: public String getButtonBgColor() {
307: return _searchButton.getButtonBgColor();
308: }
309:
310: /**
311: * Adds a button to the display box
312: */
313: public void addButton(HtmlSubmitButton b) {
314: _buttons.add(b);
315: add(b, TYPE_COMP);
316: }
317:
318: /**
319: * Updates the display box button labels for the current language<br>
320: * The language property file must have the following key structure<br>
321: * FormDisplayBox.add represents the caption for the add button.<br>
322: * FormDisplayBox.search represents the caption for the search button.<br>
323: * FormDisplayBox.cancel represents the caption for the cancel button.<br>
324: * FormDisplayBox.ok represents the caption for the ok button.<br>
325: * FormDisplayBox.undo represents the caption for the ok button.<br>
326: * SearchFormDisplayBox.dataModifiedQuestion represents the question asked if a search will overwrite unsaved data<br>
327: */
328: public void updateLocale() {
329: super .updateLocale();
330: }
331:
332: protected void processLocaleInfo() {
333: if (_updateLocale) {
334: _updateLocale = false;
335: LanguagePreferences p = getPage().getLanguagePreferences();
336: String appName = getPage().getApplicationName();
337: String descr = null;
338: String key = "FormDisplayBox.add";
339: descr = LanguageResourceFinder.getResource(appName, key, p);
340: if (descr != null)
341: _addButtonCaption = descr;
342:
343: descr = null;
344: key = "FormDisplayBox.search";
345: descr = LanguageResourceFinder.getResource(appName, key, p);
346: if (descr != null)
347: _searchButtonCaption = descr;
348:
349: descr = null;
350: key = "FormDisplayBox.cancel";
351: descr = LanguageResourceFinder.getResource(appName, key, p);
352: if (descr != null)
353: _cancelLookupButtonCaption = descr;
354:
355: descr = null;
356: key = "SearchFormDisplayBox.dataModifiedQuestion";
357: descr = LanguageResourceFinder.getResource(appName, key, p);
358: if (descr != null)
359: _dataModifiedQuestion = descr;
360:
361: super .processLocaleInfo();
362: }
363: }
364:
365: /**
366: * @return the location for displaying the buttons
367: */
368: public int getButtonDisplayLocation() {
369: return _buttonDisplayLocation;
370: }
371:
372: /**
373: * Sets the display location for a button. Valid values are BUTTON_DISPLAY_IN_HEADER and BUTTON_DISPLAY_BOX_BELOW_TABLE
374: */
375: public void setButtonDisplayLocation(int loc) {
376: _buttonDisplayLocation = loc;
377: }
378:
379: /**
380: * framework method, do not call directly
381: */
382: public boolean submitPerformed(SubmitEvent e) throws Exception {
383: if (e.getComponent() == _addButton)
384: doAdd();
385: else if (e.getComponent() == _searchButton) {
386: trySearch();
387: } else if (e.getComponent() == _cancelLookupButton)
388: if (isFromPopupLookup()) {
389: HtmlScriptGenerator gen = new HtmlScriptGenerator(
390: getPage());
391: getPage().writeScript(gen.generateCancelLookupScript());
392: } else
393: getPage().getCurrentResponse().sendRedirect(
394: getLookupReturnToURL(null, null));
395: return true;
396: }
397:
398: /**
399: * This method gets fired when the user clicks the add button. Subclasses can override it to customize behavior
400: */
401: public void doAdd() throws DataStoreException, SQLException,
402: Exception {
403: if (_listForm != null)
404: _listForm.doAdd();
405: }
406:
407: /**
408: * This method gets fired when the user clicks the search button. Subclasses can override it to customize behavior
409: */
410: public void doSearch() throws SQLException, DataStoreException,
411: Exception {
412: if (_listForm != null) {
413: _listForm.doSearch();
414: }
415: }
416:
417: /**
418: * @return the criteria builder the component is using to build the search filter
419: */
420: public QBEBuilder getCriteriaBuilder() {
421: return _criteriaBuilder;
422: }
423:
424: /**
425: * @return the criteria validator the component is using to validate entered criteria
426: */
427: public HtmlValidatorText getCriteriaValidator() {
428: return _validator;
429: }
430:
431: /**
432: * Sets the access key for the search button
433: */
434: public void setSearchButtonAccessKey(String key) {
435: _searchButton.setAccessKey(key);
436: }
437:
438: /**
439: * Sets the access key for the add button
440: */
441: public void setAddButtonAccessKey(String key) {
442: _addButton.setAccessKey(key);
443: }
444:
445: /**
446: * Sets the theme for the component
447: */
448: public void setTheme(String theme) {
449: super .setTheme(theme);
450: Props props = getPage().getPageProperties();
451: _searchButtonCaption = props.getThemeProperty(theme,
452: Props.SEARCH_FORM_DISPLAY_BOX_SEARCH_BUTTON_CAPTION);
453: _searchButtonAccessKey = props.getThemeProperty(theme,
454: Props.SEARCH_FORM_DISPLAY_BOX_SEARCH_BUTTON_ACCESS_KEY);
455: _addButtonCaption = props.getThemeProperty(theme,
456: Props.SEARCH_FORM_DISPLAY_BOX_ADD_BUTTON_CAPTION);
457: _addButtonAccessKey = props.getThemeProperty(theme,
458: Props.SEARCH_FORM_DISPLAY_BOX_ADD_BUTTON_ACCESS_KEY);
459: _cancelLookupButtonCaption = props.getThemeProperty(theme,
460: Props.SEARCH_FORM_DISPLAY_BOX_CANCEL_BUTTON_CAPTION);
461: _cancelLookupAccessKey = props.getThemeProperty(theme,
462: Props.SEARCH_FORM_DISPLAY_BOX_CANCEL_BUTTON_ACCESS_KEY);
463:
464: String st = props.getThemeProperty(theme,
465: Props.SEARCH_FORM_DISPLAY_BOX_BUTTON_LOCATION);
466: if (st != null) {
467: if (st.equalsIgnoreCase("BELOW_TABLE"))
468: setButtonDisplayLocation(BUTTON_DISPLAY_BELOW_TABLE);
469: else if (st.equalsIgnoreCase("IN_HEADER"))
470: setButtonDisplayLocation(BUTTON_DISPLAY_IN_HEADER);
471: else if (st.equalsIgnoreCase("IN_HEADER_AND_BELOW_TABLE"))
472: setButtonDisplayLocation(BUTTON_DISPLAY_IN_HEADER_AND_BELOW_TABLE);
473: }
474: st = props.getThemeProperty(theme,
475: Props.SEARCH_FORM_DISPLAY_BOX_BOTTOM_BUTTON_ALIGN);
476: if (st != null)
477: setBottomButtonAlign(st);
478: setUpButtons();
479: }
480:
481: protected void setUpButtons() {
482: super .setUpButtons();
483: if (_searchButton == null)
484: return;
485: if (_searchButtonCaption != null)
486: _searchButton.setDisplayName(_searchButtonCaption);
487: if (_searchButtonAccessKey != null)
488: _searchButton.setAccessKey(_searchButtonAccessKey);
489: if (_addButtonCaption != null)
490: _addButton.setDisplayName(_addButtonCaption);
491: if (_addButtonAccessKey != null)
492: _addButton.setAccessKey(_addButtonAccessKey);
493: if (_cancelLookupButtonCaption != null)
494: _cancelLookupButton
495: .setDisplayName(_cancelLookupButtonCaption);
496: if (_cancelLookupAccessKey != null)
497: _cancelLookupButton.setAccessKey(_cancelLookupAccessKey);
498:
499: if (_okButton != null)
500: _okButton.setDisplayName(_okButtonCap);
501: if (_cancelButton != null)
502: _cancelButton.setDisplayName(_cancelButtonCap);
503: }
504:
505: /**
506: * @return the question when asking whether to cancel an operation because the modified data will be overwritten
507: */
508: public String getDataModifiedQuestion() {
509: return _dataModifiedQuestion;
510: }
511:
512: /**
513: * sets the question when asking whether to cancel an operation because the modified data will be overwritten
514: */
515: public void setDataModifiedQuestion(String string) {
516: _dataModifiedQuestion = string;
517: }
518:
519: /**
520: * Set the access key for the lookup cancel button
521: */
522: public void setCancelButtonAccessKey(String key) {
523: _cancelLookupButton.setAccessKey(key);
524: }
525:
526: /**
527: * Sets the cancel lookup button visible or not
528: */
529: public void setCancelButtonVisible(boolean visible) {
530: _cancelLookupButtonVisible = visible;
531: }
532:
533: /**
534: * Sets the cancel lookup button visible or not
535: */
536: public void setCancelButtonCaption(String caption) {
537: if (_cancelLookupButton != null)
538: _cancelLookupButton.setDisplayName(caption);
539: }
540:
541: /**
542: * Returns the cancel lookup button caption
543: */
544: public String getCancelLookupButtonCaption() {
545: if (_cancelLookupButton == null)
546: return null;
547: else
548: return _cancelLookupButton.getDisplayName();
549: }
550:
551: /**
552: * Return the cancel lookup button visible or not
553: */
554: public boolean isCancelButtonVisible() {
555: if (_cancelLookupButton == null)
556: return false;
557: else
558: return _cancelLookupButton.getVisible();
559: }
560:
561: public void generateHTML(TagWriter t, String boxBody)
562: throws Exception {
563: processLocaleInfo();
564: boolean oldVis[] = null;
565: if (isFromLookup() || isFromPopupLookup()) {
566: oldVis = getButtonsVisible();
567: _cancelLookupButton.setVisible(_cancelLookupButtonVisible);
568: _addButton.setVisible(false);
569: }
570:
571: super .generateHTML(t, boxBody);
572:
573: if (oldVis != null)
574: setButtonVisible(oldVis);
575: }
576:
577: /**
578: * @return the DataStoreBuffer this component is using
579: */
580: public DataStoreBuffer getDataStoreBuffer() {
581: return _listForm.getDataStore();
582: }
583:
584: /**
585: * @return the add button the component is using
586: */
587: public HtmlSubmitButton getAddButton() {
588: return _addButton;
589: }
590:
591: /**
592: * @return the search button the component is using
593: */
594: public HtmlSubmitButton getSearchButton() {
595: return _searchButton;
596: }
597: }
|