001: package org.osbl.client.wings.shell.smart;
002:
003: import java.awt.Dimension;
004: import java.awt.event.ActionEvent;
005: import java.awt.event.ActionListener;
006: import java.awt.image.BufferedImage;
007: import java.io.IOException;
008: import java.util.HashMap;
009: import java.util.Map;
010:
011: import org.wings.*;
012: import org.wings.resource.DefaultURLResource;
013: import org.wings.header.Link;
014: import org.wings.session.BrowserType;
015: import org.osbl.client.wings.shell.smart.ProcessClientStyles;
016: import org.osbl.client.wings.shell.SVGButtonRenderer;
017: import org.osbl.client.wings.shell.Templates;
018: import org.osbl.client.wings.*;
019:
020: /**
021: * The <code>SideBarPane</code> could contain components and each
022: * component you add with {@link this#addTab(String, org.wings.SComponent)}
023: * will get a tab button to set the component visible or not. You
024: * are able to pin the sidebar if you set the pinnable as true.
025: *
026: * @author leon
027: * @author rro
028: */
029: public class SideBarPane extends SPanel {
030: private final static String SVG_LEFT = "svg/tabbed_pane_left.svg";
031: private final static String SVG_LEFT_SELECTED = "svg/tabbed_pane_left_selected.svg";
032: private final static String SVG_LEFT_DISABLED = "svg/tabbed_pane_left_disabled.svg";
033: private final static String SVG_RIGHT = "svg/tabbed_pane_right.svg";
034: private final static String SVG_RIGHT_SELECTED = "svg/tabbed_pane_right_selected.svg";
035: private final static String SVG_RIGHT_DISABLED = "svg/tabbed_pane_right_disabled.svg";
036:
037: // Styles for sidebar on the left.
038: protected Link leftVisibleStyles = new Link("stylesheet", null,
039: "text/css", null, new DefaultURLResource(
040: isIE() ? "../templates/navigations-msie.css"
041: : "../templates/navigations.css"));
042:
043: // Styles for sidebar on the right.
044: protected Link rightVisibleStyles = new Link("stylesheet", null,
045: "text/css", null, new DefaultURLResource(
046: isIE() ? "../templates/tools-msie.css"
047: : "../templates/tools.css"));
048:
049: // Whether the sidebar is pinnable or not.
050: private boolean pinnable;
051:
052: // Whether the sidebar is pinned or not.
053: private boolean pinned = true;
054:
055: // The tab area contains the tab icons.
056: private SPanel tabArea;
057:
058: // The pin button on the tab area.
059: private SButton pinButton;
060:
061: // The placement of the sidebar.
062: private int placement;
063:
064: // SComponent to SButton mapping - component -> tab button.
065: private Map<SComponent, SButton> component2Button = new HashMap<SComponent, SButton>();
066:
067: // The current activated button.
068: private SButton activeButton;
069:
070: // The current activated component.
071: private SComponent activeComponent;
072: private Map<String, SImageIcon> icons = new HashMap<String, SImageIcon>();
073: private boolean shaded = true;
074:
075: /**
076: * A new sidebar pane that is not pinnable.
077: *
078: * @param placement The placement on the frame.
079: */
080: public SideBarPane(int placement) {
081: this (placement, false);
082: }
083:
084: /**
085: * A new sidebar pane.
086: *
087: * @param placement The placement on the frame.
088: * @param pinnable Whether the sidebar should be pinnable
089: * or not.
090: */
091: public SideBarPane(int placement, boolean pinnable) {
092: this .placement = placement;
093: this .pinnable = pinnable;
094:
095: try {
096: setLayout(new STemplateLayout(
097: Templates
098: .load(placement == SConstants.LEFT ? "/sidebar_left.html"
099: : "/sidebar_right.html")));
100: } catch (IOException ex) {
101: throw new RuntimeException(ex);
102: }
103:
104: setPreferredSize(SDimension.FULLAREA);
105:
106: tabArea = new SPanel(new SFlowDownLayout());
107: tabArea.add(createPinButton());
108: add(tabArea, "tabs");
109: }
110:
111: /**
112: * Let the code generator delegate write the component's code
113: * to the device. The code generator is the actual 'plaf'.
114: *
115: * @param device the Device to write into
116: * @throws IOException Thrown if the connection to the client gets broken,
117: * for example when the user stops loading
118: public void write(Device device) throws IOException {
119: Utils.renderContainer(device, this);
120: }
121: */
122:
123: /**
124: * Returns whether the sidebar is allows to be pinned
125: * or not.
126: *
127: * @return Whether the sidebar is allows to be pinned
128: * or not.
129: */
130: public boolean isPinnable() {
131: return pinnable;
132: }
133:
134: /**
135: * Sets whether the sidebar should be pinnable or not.
136: *
137: * @param pinnable Whether the sidebar should be pinnable
138: * or not.
139: */
140: public void setPinnable(boolean pinnable) {
141: this .pinnable = pinnable;
142: }
143:
144: /**
145: * Returns whether the sidebar is pinned or unpinned.
146: *
147: * @return Whether the sidebar is pinned or unpinned.
148: */
149: public boolean isPinned() {
150: return pinned;
151: }
152:
153: /**
154: * Shows the sidebar.
155: */
156: public void show() {
157: // empty
158: }
159:
160: /**
161: * Hides the sidebar.
162: */
163: public void hide() {
164: if (activeButton != null) {
165: activeButton.setIcon(getButtonIcon(activeButton
166: .getToolTipText(), true, false));
167: activeButton = null;
168: }
169:
170: if (activeComponent != null) {
171: hideTab(activeComponent);
172: }
173: }
174:
175: /**
176: * Adds a component to the sidebar. The title will be used for
177: * tab title creation.
178: *
179: * @param title The title of the tab.
180: * @param c The component that should be shown in a tab.
181: */
182: public void addTab(final String title, SComponent c) {
183: c.setVisible(false);
184: final SButton button = new SButton() {
185: public void requestFocus() {
186: }
187: };
188: button.setToolTipText(title);
189: button.setStyle(ProcessClientStyles.SIDE_BAR_BUTTON);
190: button.setIcon(getButtonIcon(title, true, false));
191: button.setDisabledIcon(getButtonIcon(title, false, false));
192: button.putClientProperty("component", c);
193:
194: component2Button.put(c, button);
195:
196: button.addActionListener(new ActionListener() {
197: public void actionPerformed(ActionEvent actionEvent) {
198: if (activeButton != null && activeButton != button) {
199: activeButton.setIcon(getButtonIcon(activeButton
200: .getToolTipText(), true, false));
201: }
202:
203: // Close side bar pane if selected and open button was pressed.
204: if (activeButton != null && activeButton == button) {
205: hide();
206: }
207: // Open side bar pane if selected or display another c.
208: else {
209: activeButton = button;
210: activeButton.setIcon(getButtonIcon(title, true,
211: true));
212: showTab((SComponent) activeButton
213: .getClientProperty("component"));
214: }
215: }
216: });
217:
218: tabArea.add(button);
219: }
220:
221: /**
222: * Removes the component from the sidebar.
223: *
224: * @param c The component that should be removed from
225: * sidebar.
226: */
227: public void removeTab(SComponent c) {
228: SButton button = component2Button.remove(c);
229: tabArea.remove(button);
230:
231: if (button == activeButton) {
232: if (activeComponent != null) {
233: remove(activeComponent);
234: }
235: activeComponent = null;
236: activeButton = null;
237: makeVisible(false);
238: }
239: }
240:
241: public boolean getEnabledFor(SComponent component) {
242: SButton button = component2Button.get(component);
243: return button.isEnabled();
244: }
245:
246: public void setEnabledFor(SComponent component, boolean enabled) {
247: SButton button = component2Button.get(component);
248: button.setEnabled(enabled);
249: if (button == activeButton)
250: hide();
251: }
252:
253: /**
254: * Set the visibility.
255: *
256: * @param visible wether this component will show or not
257: */
258: public void setVisible(boolean visible) {
259:
260: if (visible == isVisible())
261: return;
262:
263: super .setVisible(visible);
264:
265: if (activeComponent != null) {
266: activeComponent.setVisible(visible);
267: }
268: }
269:
270: /**
271: * Show the component on the sidebar.
272: *
273: * @param c The component that will be shown.
274: */
275: protected void showTab(SComponent c) {
276: if (c != null) {
277: if (activeComponent != null) {
278: activeComponent.setVisible(false);
279: remove(activeComponent);
280: activeButton.setIcon(getButtonIcon(activeButton
281: .getToolTipText(), true, false));
282: }
283:
284: c.setVisible(true);
285: activeComponent = c;
286: add(activeComponent, "content");
287: activeButton = component2Button.get(c);
288: if (activeButton != null) {
289: activeButton.setIcon(getButtonIcon(activeButton
290: .getToolTipText(), true, true));
291: }
292: makeVisible(true);
293: }
294: }
295:
296: /**
297: * Hide the component on the sidebar.
298: *
299: * @param c The component that will be hidden.
300: */
301: protected void hideTab(SComponent c) {
302: if (c != null) {
303: makeVisible(false);
304: remove(c);
305: activeComponent = null;
306: c.setVisible(false);
307: }
308: }
309:
310: /**
311: * Creates the pin button.
312: */
313: private SButton createPinButton() {
314: pinButton = new SButton(XIcons.PIN_PINNED);
315: pinButton.setStyle(ProcessClientStyles.SIDE_BAR_BUTTON);
316: pinButton.setVisible(false);
317: pinButton.addActionListener(new ActionListener() {
318:
319: /**
320: * Invoked when an action occurs.
321: */
322: public void actionPerformed(ActionEvent e) {
323:
324: SIcon icon;
325: if (pinned) {
326: icon = XIcons.PIN_UNPINNED;
327: } else {
328: icon = XIcons.PIN_PINNED;
329: }
330: pinButton.setIcon(icon);
331:
332: // Change pin state.
333: pinned = !pinned;
334: }
335: });
336:
337: return pinButton;
338: }
339:
340: /**
341: * Makes the sidebar visible or unvisible on current parent
342: * frame. It decides whether the sidebar is on the left or
343: * on the right.
344: *
345: * @param visible Whether the sidebar should be visible or
346: * not.
347: */
348: private void makeVisible(boolean visible) {
349: if (shaded == !visible)
350: return;
351:
352: shaded = !visible;
353:
354: // Show pin button if the sidebar is visible and the sidebar
355: // allows a pinned state.
356: pinButton.setVisible(visible && pinnable);
357:
358: SFrame parentFrame = getParentFrame();
359: if (placement == SConstants.LEFT) {
360: if (visible)
361: parentFrame.addHeader(leftVisibleStyles);
362: else
363: parentFrame.removeHeader(leftVisibleStyles);
364: } else {
365: if (visible)
366: parentFrame.addHeader(rightVisibleStyles);
367: else
368: parentFrame.removeHeader(rightVisibleStyles);
369: }
370: if (isIE())
371: parentFrame.reload();
372: }
373:
374: /**
375: * Returns whether the browser type equals internet explorer
376: * or not.
377: *
378: * @return Whether the browser type equals internet explorer
379: * or not.
380: */
381: private boolean isIE() {
382: return BrowserType.IE.equals(getSession().getUserAgent()
383: .getBrowserType());
384: }
385:
386: private SImageIcon getButtonIcon(String text, boolean enabled,
387: boolean selected) {
388: String key;
389:
390: if (!enabled)
391: key = text + "_disabled";
392: else
393: key = text + (selected ? "_selected" : "_deselected");
394:
395: SImageIcon icon = icons.get(key);
396: if (icon == null) {
397: SVGButtonRenderer renderer = SVGButtonRenderer
398: .getInstance();
399: Dimension d = renderer.calculateButtonImageSize(text);
400: Dimension newDim = new Dimension(d.height, d.width + 10);
401: String res;
402: if (placement == SConstants.LEFT) {
403: if (!enabled)
404: res = SVG_LEFT_DISABLED;
405: else
406: res = selected ? SVG_LEFT_SELECTED : SVG_LEFT;
407: } else {
408: if (!enabled)
409: res = SVG_RIGHT_DISABLED;
410: else
411: res = selected ? SVG_RIGHT_SELECTED : SVG_RIGHT;
412: }
413: BufferedImage img = renderer.retrieveRenderedButtonImage(
414: text, res, newDim);
415: icon = new SImageIcon(img, isIE() ? "image/gif"
416: : "image/png");
417: icons.put(key, icon);
418: }
419: return icon;
420: }
421: }
|