001: /*
002: * Copyright 2000,2005 wingS development team.
003: *
004: * This file is part of wingS (http://wingsframework.org).
005: *
006: * wingS is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU Lesser General Public License
008: * as published by the Free Software Foundation; either version 2.1
009: * of the License, or (at your option) any later version.
010: *
011: * Please see COPYING for the complete licence.
012: */
013:
014: package wingset;
015:
016: import org.wings.*;
017: import org.wings.border.SEmptyBorder;
018: import org.wings.event.*;
019:
020: import java.awt.*;
021: import java.awt.event.ActionEvent;
022:
023: /**
024: * Example demonstrating the capabilities of wings regarding
025: * <ul>
026: * <li>Back button handling</li>
027: * <li>Read-only mode with support for operations on old views</li>
028: * </ul>
029: *
030: * @author bschmid
031: */
032: public class BackButtonTest extends WingSetPane {
033: private final SPanel mainPanel = new SPanel();
034: private final SLabel epochLabel = new SLabel();
035: private final SButton newEpochButton = new SButton(
036: "After changing mode, click here SEVERAL times generate browser history entries");
037:
038: private final SButton regularButton = new SButton("Regular button");
039: private final SLabel regularButtonSignal = new SLabel(
040: "Regular button pressed");
041:
042: private final SButton virtualBackButton = new SButton(
043: "Virtual back button");
044: private final SLabel virtualBackButtonSignal = new SLabel(
045: "Virtual back button pressed");
046:
047: private final SButton nonEpochedButton = new SButton(
048: "Non epoch-checked button");
049: private final SLabel nonEpochedButtonSignal = new SLabel(
050: "Non epoch-checked button accepted");
051:
052: protected SComponent createControls() {
053: return null;
054: }
055:
056: protected SComponent createExample() {
057: mainPanel.setLayout(new SFlowDownLayout());
058: mainPanel.setHorizontalAlignment(CENTER);
059: mainPanel.setPreferredSize(new SDimension(550,
060: SDimension.AUTO_INT));
061:
062: final SLabel titleLabel = new SLabel(
063: "wingS browser back-button detection\n ");
064: titleLabel.setFont(new SFont("sans-serif", SFont.PLAIN, 16));
065: mainPanel.add(titleLabel);
066:
067: final SLabel instructions = new SLabel(
068: "The epoch checking mechanism allows wingS "
069: + "to tackle the browser back navigation in threee different ways demonstrated in this example.\n\n"
070: + "To try this example just choose one of the described ways, click several time the buttons and try "
071: + "what happens if you go back with your browser.");
072: instructions.setWordWrap(true);
073: mainPanel.add(instructions);
074:
075: mainPanel.addRenderListener(new SRenderListener() {
076: public void startRendering(SRenderEvent e) {
077: epochLabel.setText("<html><p>Current epoch: <b>"
078: + epochLabel.getParentFrame().getEventEpoch()
079: + "</b><p>");
080: }
081:
082: public void doneRendering(SRenderEvent e) {
083: virtualBackButtonSignal.setVisible(false);
084: regularButtonSignal.setVisible(false);
085: nonEpochedButtonSignal.setVisible(false);
086: }
087: });
088:
089: virtualBackButton
090: .addActionListener(new java.awt.event.ActionListener() {
091: public void actionPerformed(ActionEvent e) {
092: virtualBackButtonSignal.setVisible(true);
093: }
094: });
095:
096: SPanel signalPanel = new SPanel(new SFlowLayout());
097: signalPanel.add(virtualBackButtonSignal);
098: virtualBackButtonSignal.setBorder(new SEmptyBorder(10, 10, 10,
099: 10));
100: virtualBackButtonSignal.setBackground(Color.YELLOW);
101: virtualBackButtonSignal.setFont(new SFont(SFont.BOLD));
102: virtualBackButtonSignal.setVisible(false);
103:
104: signalPanel.add(regularButtonSignal);
105: regularButtonSignal.setBorder(new SEmptyBorder(10, 10, 10, 10));
106: regularButtonSignal.setBackground(Color.GREEN);
107: regularButtonSignal.setFont(new SFont(SFont.BOLD));
108: regularButtonSignal.setVisible(false);
109:
110: signalPanel.add(nonEpochedButtonSignal);
111: nonEpochedButtonSignal.setBorder(new SEmptyBorder(10, 10, 10,
112: 10));
113: nonEpochedButtonSignal.setBackground(Color.GREEN);
114: nonEpochedButtonSignal.setFont(new SFont(SFont.BOLD));
115: nonEpochedButtonSignal.setVisible(false);
116: mainPanel.add(signalPanel);
117:
118: regularButton.setVisible(false);
119: nonEpochedButton.setVisible(false);
120:
121: final SButtonGroup buttonGroup = new SButtonGroup();
122: final SRadioButton postMode = new SRadioButton(
123: "<html><b>Default:</b> Drop and ignore requests from old views"
124: + " and just redisplay the current view. This ensures that no activity is falsely triggered and the "
125: + "user only starts actions he expects. Typicall web applications are operating with HTTP POST, so "
126: + "most wrowsers will present a 'repost form' confirmation dialog on navigating back.<p> ");
127: final SRadioButton getMode = new SRadioButton(
128: "<html><b>Extended default:</b> Same as the default case, "
129: + "but you register a virtual \"back\" button. wingS will <i>immediately</i> notify and catch "
130: + "back operations and and trigger your virtual back button by heuristics. "
131: + "Probably you want to use this. event i.e. to display a information message or trigger applaciation backs/undos."
132: + "This example switches into HTTP GET mode to avoid the anyoing 'repost form' confirmations.<p> ");
133: final SRadioButton getMode2 = new SRadioButton(
134: "<html><b>Allow:</b> Allows and doesn't intercept back navigations. "
135: + "The user will be able to see and click within 'old views'. Just as the default case"
136: + "wingS will ignored by default clicks on any component, unless you marked it via <b>setEpochCheckEnabled()</b> "
137: + "to be always valid. From the developers perspective your application logic must be aware that those "
138: + "non-epoched components will be able to fire events at any time."
139: + "In this example clicks on the <b>regular</b> buttons will be dropped and lead to the back button event, "
140: + "while clicking on the <b>Not epoch-checked button</b> will also accepted in old views.<p> ");
141: buttonGroup.add(postMode);
142: buttonGroup.add(getMode);
143: buttonGroup.add(getMode2);
144: postMode.setSelected(true);
145: postMode.setWordWrap(true);
146: getMode.setWordWrap(true);
147: getMode2.setWordWrap(true);
148: mainPanel.add(postMode);
149: mainPanel.add(getMode);
150: mainPanel.add(getMode2);
151:
152: buttonGroup
153: .addActionListener(new java.awt.event.ActionListener() {
154: public void actionPerformed(ActionEvent e) {
155: regularButton.setVisible(false);
156: nonEpochedButton.setVisible(false);
157:
158: if (buttonGroup.getSelection() == postMode) {
159: getForm().setPostMethod(true);
160: mainPanel.getParentFrame().setNoCaching(
161: true);
162: } else if (buttonGroup.getSelection() == getMode) {
163: getForm().setPostMethod(false);
164: mainPanel.getParentFrame().setNoCaching(
165: true);
166: } else if (buttonGroup.getSelection() == getMode2) {
167: getForm().setPostMethod(false);
168: mainPanel.getParentFrame().setNoCaching(
169: false);
170: // Allow events on this button from old views
171: nonEpochedButton
172: .setEpochCheckEnabled(false);
173: // Turn of components included in every request.
174: // Otherwise we would receive irritiating back button events in this demo.
175: postMode.setEpochCheckEnabled(false);
176: getMode.setEpochCheckEnabled(false);
177: getMode2.setEpochCheckEnabled(false);
178: getForm().setEpochCheckEnabled(false);
179: regularButton.setVisible(true);
180: nonEpochedButton.setVisible(true);
181: }
182: }
183:
184: private SForm getForm() {
185: return (SForm) getParentFrame()
186: .getContentPane();
187: }
188: });
189:
190: mainPanel.add(epochLabel);
191:
192: newEpochButton
193: .addActionListener(new java.awt.event.ActionListener() {
194: public void actionPerformed(ActionEvent e) {
195: mainPanel.reload(); // Force invalidaton of epoch for demonstration purposes
196: }
197: });
198: mainPanel.add(newEpochButton);
199:
200: regularButton
201: .addActionListener(new java.awt.event.ActionListener() {
202: public void actionPerformed(ActionEvent e) {
203: regularButtonSignal.setVisible(true);
204: }
205: });
206: mainPanel.add(regularButton);
207:
208: nonEpochedButton
209: .addActionListener(new java.awt.event.ActionListener() {
210: public void actionPerformed(ActionEvent e) {
211: nonEpochedButtonSignal.setVisible(true);
212: }
213: });
214: mainPanel.add(nonEpochedButton);
215:
216: mainPanel.addParentFrameListener(new SParentFrameListener() {
217: public void parentFrameAdded(SParentFrameEvent e) {
218: mainPanel.getParentFrame().setBackButton(
219: virtualBackButton);
220:
221: mainPanel.getParentFrame()
222: .addInvalidLowLevelEventListener(
223: new SInvalidLowLevelEventListener() {
224: public void invalidLowLevelEvent(
225: InvalidLowLevelEvent e) {
226: log
227: .info("Invalid Low-Level event detected on "
228: + e.getSource());
229: }
230: });
231: mainPanel.removeParentFrameListener(this );
232: }
233:
234: public void parentFrameRemoved(SParentFrameEvent e) {
235: }
236: });
237: return mainPanel;
238: }
239: }
|