001: /*
002: *
003: * (c) Copyright 2004 - 2007 osbl development team.
004: *
005: * This file is part of the osbl (http://osbl.wilken.de).
006: *
007: * the osbl is free software; you can redistribute it and/or modify
008: * it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2.1
010: * of the License, or (at your option) any later version.
011: *
012: * Please see COPYING for the complete licence.
013: */
014: package org.osbl.client.wings.shell.smart;
015:
016: import java.awt.event.*;
017: import java.awt.*;
018: import java.io.*;
019: import java.util.*;
020: import java.util.List;
021: import java.beans.PropertyChangeListener;
022: import java.beans.PropertyChangeEvent;
023:
024: import javax.swing.*;
025: import javax.swing.table.AbstractTableModel;
026: import javax.swing.event.*;
027: import javax.swing.tree.TreeModel;
028:
029: import org.conform.format.StringTemplate;
030: import org.wings.*;
031: import org.wings.event.*;
032: import org.wings.table.SDefaultTableCellRenderer;
033: import org.wings.header.*;
034: import org.wings.plaf.css.*;
035: import org.wings.resource.*;
036: import org.wings.script.*;
037: import org.wings.session.*;
038:
039: import org.osbl.client.wings.devtools.*;
040: import org.osbl.client.wings.*;
041: import org.osbl.client.wings.shell.Templates;
042: import org.osbl.client.wings.shell.*;
043: import org.osbl.client.wings.shell.Window;
044:
045: /**
046: * @author hengels
047: * @version $Revision: 1.9 $
048: */
049: public class ProcessClient extends Client {
050: protected SFrame frame;
051:
052: protected SideBarPane navigationsSideBar;
053: protected SideBarPane toolsSideBar;
054:
055: protected Menu menu;
056: protected SForm form;
057:
058: private SPanel headerPanel;
059:
060: protected SPanel header;
061: protected SPanel titleBar;
062: protected SPanel statusBar;
063: protected SPanel controlBar;
064: protected SPanel content;
065:
066: private Map<String, SComponent> navigations;
067: private Map<String, Tool> tools;
068:
069: protected SLabel titleLabel;
070: protected SButton statusLabel;
071: protected SLabel detailLabel;
072:
073: private SComponent shownComponent;
074:
075: protected Link navigationsVisibleStyles = new Link("stylesheet",
076: null, "text/css", null, new DefaultURLResource(
077: isIE() ? "../templates/navigations-msie.css"
078: : "../templates/navigations.css"));
079: protected Link toolsVisibleStyles = new Link("stylesheet", null,
080: "text/css", null, new DefaultURLResource(
081: isIE() ? "../templates/tools-msie.css"
082: : "../templates/tools.css"));
083: private NoWindow noWindow;
084:
085: public void initialize() {
086: navigations = new HashMap<String, SComponent>();
087: tools = new HashMap<String, Tool>();
088:
089: frame = new SFrame("Process Client");
090: frame.addHeader(new Link("shortcut icon", null,
091: "image/vnd.microsoft.icon", null, new SURLIcon(
092: "../icon/favicon.ico")));
093: headerPanel = new SPanel(new SGridLayout());
094:
095: header = new SPanel(Templates.loadLayout("header.html"));
096: titleBar = new SPanel(new SBorderLayout());
097: statusBar = new SPanel(new SFlowLayout(SConstants.LEFT_ALIGN));
098: controlBar = new SPanel(new SGridBagLayout());
099: content = new SPanel(new SBorderLayout());
100:
101: titleLabel = new SLabel();
102: statusLabel = new SButton(XIcons.EMPTY);
103: detailLabel = new SLabel();
104:
105: Session session = getSession();
106: ((TextFieldCG) session.getCGManager().getCG(STextField.class))
107: .setHorizontalOversize(6);
108: ((TextAreaCG) session.getCGManager().getCG(STextArea.class))
109: .setHorizontalOversize(5);
110: ((TableCG) session.getCGManager().getCG(STable.class))
111: .setHorizontalOversize(22);
112:
113: form = (SForm) frame.getContentPane();
114: form.setLayout(Templates.loadLayout("frame.html"));
115: form.setPreferredSize(SDimension.FULLAREA);
116:
117: // Left sidebar
118: navigationsSideBar = new SideBarPane(SConstants.LEFT, true);
119: navigationsSideBar
120: .setStyle(ProcessClientStyles.LEFT_SIDEBAR_COLLAPSED);
121: form.add(navigationsSideBar, ProcessClientAreas.LEFT_SIDEBAR);
122:
123: // Right sidebar
124: toolsSideBar = new SideBarPane(SConstants.RIGHT);
125: toolsSideBar
126: .setStyle(ProcessClientStyles.RIGHT_SIDEBAR_COLLAPSED);
127: form.add(toolsSideBar, ProcessClientAreas.RIGHT_SIDEBAR);
128:
129: headerPanel.setHorizontalAlignment(SConstants.RIGHT_ALIGN);
130: SLabel logo = new SLabel(new SURLIcon("../icon/logo.gif"));
131: logo.setVerticalAlignment(SConstants.CENTER_ALIGN);
132:
133: // Header
134: header.setStyle(ProcessClientStyles.HEADER);
135: header.setPreferredSize(SDimension.FULLWIDTH);
136: header.setVerticalAlignment(SConstants.CENTER_ALIGN);
137: header.add(headerPanel, "buttons");
138: header.add(logo, "logo");
139:
140: form.add(header, ProcessClientAreas.HEADER);
141:
142: // Menu
143: menu = new Menu();
144: menu.setStyle(menu.getStyle() + " " + ProcessClientAreas.MENU);
145: form.add(menu, ProcessClientAreas.MENU);
146:
147: // TitleBar
148: titleLabel.setStyle(ProcessClientStyles.TITLE);
149: titleLabel.setPreferredSize(SDimension.FULLAREA);
150:
151: SButton printButton = new SButton(getActionProvider()
152: .configure(new PrintAction()));
153: printButton.setText(null);
154: //titleBar.add(printButton, SBorderLayout.EAST);
155:
156: titleBar.add(titleLabel, SBorderLayout.WEST);
157: form.add(titleBar, ProcessClientAreas.TITLE);
158:
159: // ToolBar
160: controlBar.setStyle(ProcessClientStyles.ACTION_BAR);
161: controlBar.setPreferredSize(SDimension.FULLAREA);
162: form.add(controlBar, ProcessClientAreas.ACTION_BAR);
163:
164: // Status Bar
165: form.add(statusBar, ProcessClientAreas.STATUS_BAR);
166:
167: detailLabel.setName("statusDetails");
168: String jsToggleStatusDetails = "function toggleStatusDetails() {\n"
169: + " var details = document.getElementById('statusDetails');\n"
170: + " var status = document.getElementById('status');\n"
171: + " if (details.style.display != 'block') {\n"
172: + " details.style.display = 'block';\n"
173: + " var bounds = new Array(1);\n"
174: + " bounds[0] = new wpm_Bounds(details);\n"
175: + " wpm_toggleFormElements(bounds);\n"
176: + " }\n"
177: + " else {\n"
178: + " details.style.display = 'none';\n"
179: + " wpm_toggleFormElements();\n"
180: + " }\n"
181: + "}\n";
182: statusLabel.addScriptListener(new JavaScriptListener(
183: "onmousedown", "toggleStatusDetails(); return false;",
184: jsToggleStatusDetails));
185: statusLabel.addScriptListener(new JavaScriptListener("onclick",
186: "return false;")); // prevent submit
187: statusLabel.setStyle("borderless_form");
188: statusBar.add(statusLabel);
189: statusBar.add(detailLabel);
190:
191: content.setPreferredSize(SDimension.FULLAREA);
192: // Status Bar
193: form.add(content, ProcessClientAreas.CONTENT_AREA);
194:
195: String styleSheet = loadResourceAsString(isIE() ? "/process_client-msie.css"
196: : "/process_client.css");
197: Properties colorScheme = loadColorScheme();
198: StringTemplate template = new StringTemplate(styleSheet);
199: template.setMap(colorScheme);
200: styleSheet = template.toString();
201: frame.addHeader(new Link("stylesheet", null, "text/css", null,
202: new StringResource(styleSheet, "css", "text/css")));
203: frame.addHeader(new Link("stylesheet", null, "text/css", null,
204: new DefaultURLResource(
205: isIE() ? "../templates/frame-msie.css"
206: : "../templates/frame.css")));
207: frame.addHeader(new Script("text/javascript",
208: new DefaultURLResource("../js/utils.js")));
209: frame.show();
210:
211: addNavigation("windows", getResourceProvider().getMessage(
212: "navigation.windows"), null, new WindowStacksList(
213: getWindowStacksModel()));
214:
215: noWindow = new NoWindow(new SLabel(
216: "Please choose from the Navigation Sidebar!"));
217:
218: /*
219: Window identityEditorWindow = new Window(new SLabel("Identity Manager Dummy"), "identity manager dummy");
220: pushWindow(identityEditorWindow);
221: Window identityListWindow = new Window(new SLabel("Identity List Dummy"), "identity list dummy");
222: Window identityFormWindow = new Window(new SLabel("Identity Editor Dummy"), "identity editor dummy");
223: pushWindow(identityEditorWindow, identityListWindow);
224: popWindow(identityListWindow);
225: pushWindow(identityEditorWindow, identityFormWindow);
226: pushWindow(new Window(new SLabel("Process Manager Dummy"), "process manager dummy"));
227: */
228: }
229:
230: public static class WindowStacksList extends STable {
231: final WindowStacksModel windowStacksModel;
232:
233: public WindowStacksList(
234: final WindowStacksModel windowStacksModel) {
235: super (new AbstractTableModel() {
236: public int getRowCount() {
237: return windowStacksModel.getSize();
238: }
239:
240: public int getColumnCount() {
241: return 2;
242: }
243:
244: public Object getValueAt(int rowIndex, int columnIndex) {
245: return windowStacksModel.getElementAt(rowIndex);
246: }
247: });
248: this .windowStacksModel = windowStacksModel;
249:
250: getColumnModel().getColumn(0).setWidth("*");
251: getColumnModel().getColumn(1).setWidth("22");
252: setPreferredSize(SDimension.FULLWIDTH);
253: setHeaderVisible(false);
254: setRowSelectionRenderer(null);
255: setEditable(false);
256:
257: // adapt list selection to model changes
258: windowStacksModel.addChangeListener(new ChangeListener() {
259: public void stateChanged(ChangeEvent e) {
260: if (getSelectedRow() != WindowStacksList.this .windowStacksModel
261: .getActiveStack())
262: setSelectedRow(WindowStacksList.this .windowStacksModel
263: .getActiveStack());
264: }
265: });
266: windowStacksModel
267: .addListDataListener(new ListDataListener() {
268: public void intervalAdded(ListDataEvent e) {
269: ((AbstractTableModel) getModel())
270: .fireTableRowsInserted(e
271: .getIndex0(), e.getIndex1());
272: }
273:
274: public void intervalRemoved(ListDataEvent e) {
275: ((AbstractTableModel) getModel())
276: .fireTableRowsDeleted(
277: e.getIndex0(), e
278: .getIndex1());
279: }
280:
281: public void contentsChanged(ListDataEvent e) {
282: ((AbstractTableModel) getModel())
283: .fireTableRowsUpdated(
284: e.getIndex0(), e
285: .getIndex1());
286: }
287: });
288:
289: // adapt model to list selection changes
290: setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
291: addSelectionListener(new ListSelectionListener() {
292: public void valueChanged(ListSelectionEvent e) {
293: //int i = Math.min(WindowStacksList.this.windowStacksModel.getSize() - 1, getSelectedRow());
294: WindowStacksList.this .windowStacksModel
295: .setActiveStack(getSelectedRow());
296: }
297: });
298:
299: addMouseListener(new SMouseListener() {
300: public void mouseClicked(SMouseEvent e) {
301: SPoint point = e.getPoint();
302: if (columnAtPoint(point) == 1) {
303: Stack<Window> stack = WindowStacksList.this .windowStacksModel
304: .getElementAt(rowAtPoint(point));
305: WindowStacksList.this .windowStacksModel
306: .remove(stack);
307: e.consume();
308: }
309: }
310: });
311: setDefaultRenderer(new SDefaultTableCellRenderer() {
312: public SComponent getTableCellRendererComponent(
313: STable table, Object value, boolean selected,
314: int row, int col) {
315: if (col == 1) {
316: setText(null);
317: setIcon(XIcons.ERROR);
318: } else {
319: Stack<Window> stack = (Stack<Window>) value;
320: String titleCode = stack.get(0).getTitleCode();
321: Object[] titleArguments = stack.get(0)
322: .getTitleArguments();
323: String text = titleCode != null ? Client
324: .getInstance().getResourceProvider()
325: .getMessage(titleCode, titleArguments)
326: : "no name";
327: if (text.length() > 24)
328: text = text.substring(0, 20) + " ...";
329: setText(text);
330: setIcon(null);
331: }
332: return this ;
333: }
334: });
335: }
336: }
337:
338: public void setMenuTreeModel(TreeModel menuTreeModel) {
339: menu.setModel(menuTreeModel);
340: }
341:
342: private Properties loadColorScheme() {
343: try {
344: Properties colorScheme = new Properties();
345: colorScheme.load(new FileInputStream(getSession()
346: .getServletContext().getRealPath(
347: "/colors.properties")));
348: return colorScheme;
349: } catch (IOException e) {
350: throw new RuntimeException(e);
351: }
352: }
353:
354: private String loadResourceAsString(String path) {
355: try {
356: InputStream in = new FileInputStream(getSession()
357: .getServletContext().getRealPath(path));
358: ByteArrayOutputStream out = new ByteArrayOutputStream(in
359: .available());
360: int len;
361: byte[] bytes = new byte[256];
362: while ((len = in.read(bytes)) > -1)
363: out.write(bytes, 0, len);
364: return out.toString();
365: } catch (IOException e) {
366: throw new RuntimeException(e);
367: }
368: }
369:
370: public void addNavigation(String character, String title,
371: SIcon icon, SComponent component) {
372: component.putClientProperty("character", character);
373: navigationsSideBar.addTab(title, component);
374: navigations.put(character, component);
375: }
376:
377: public void removeNavigation(String character) {
378: SComponent component = navigations.remove(character);
379: navigationsSideBar.removeTab(component);
380: }
381:
382: public void removeNavigation(SComponent component) {
383: String character = (String) component
384: .getClientProperty("character");
385: navigations.remove(character);
386: navigationsSideBar.removeTab(component);
387: }
388:
389: public SComponent getNavigation(String character) {
390: return navigations.get(character);
391: }
392:
393: public void clearNavigations() {
394: for (Iterator<Map.Entry<String, SComponent>> iterator = navigations
395: .entrySet().iterator(); iterator.hasNext();) {
396: Map.Entry<String, SComponent> entry = iterator.next();
397: navigationsSideBar.removeTab(entry.getValue());
398: iterator.remove();
399: }
400: }
401:
402: protected void setStatusMessage(Message message) {
403: if (message != null && message.getMessage() != null) {
404: switch (message.getType()) {
405: case Message.TYPE_INFO:
406: statusLabel.setStyle("status_info");
407: statusLabel.setIcon(XIcons.INFO);
408: break;
409: case Message.TYPE_WARNING:
410: statusLabel.setStyle("status_warning");
411: statusLabel.setIcon(XIcons.WARNING);
412: break;
413: case Message.TYPE_ERROR:
414: statusLabel.setStyle("status_error");
415: statusLabel.setIcon(XIcons.ERROR);
416: break;
417: }
418: statusLabel.setText(message.getMessage());
419: detailLabel.setText(message.getDetail());
420: } else {
421: statusLabel.setIcon(XIcons.EMPTY);
422: statusLabel.setText("");
423: detailLabel.setText(null);
424: }
425: }
426:
427: protected void setDevelopmentActions(List<Action> developmentActions) {
428: if (developmentTool != null)
429: developmentTool.setSpecificActions(developmentActions);
430: }
431:
432: protected void setHelpCode(String helpCode) {
433: if (contextHelpTool != null)
434: contextHelpTool.setHelpCode(helpCode);
435: }
436:
437: PropertyChangeListener toolChangeListener = new PropertyChangeListener() {
438: public void propertyChange(PropertyChangeEvent evt) {
439: if ("enabled".equals(evt.getPropertyName())) {
440: Tool tool = (Tool) evt.getSource();
441: toolsSideBar.setEnabledFor(tool.getComponent(), tool
442: .isEnabled());
443: }
444: }
445: };
446:
447: protected void setTools(List<Tool> tools) {
448: for (Iterator<Tool> iterator = this .tools.values().iterator(); iterator
449: .hasNext();) {
450: Tool tool = iterator.next();
451: if (tool != developmentTool) {
452: toolsSideBar.removeTab(tool.getComponent());
453: iterator.remove();
454: tool.removePropertyChangeListener(toolChangeListener);
455: }
456: }
457:
458: if (tools != null) {
459: for (Iterator iterator = tools.iterator(); iterator
460: .hasNext();) {
461: Tool tool = (Tool) iterator.next();
462: this .tools.put((String) tool.getValue(Tool.KEY), tool);
463: toolsSideBar.addTab((String) tool.getValue(Tool.NAME),
464: tool.getComponent());
465: tool.addPropertyChangeListener(toolChangeListener);
466: toolsSideBar.setEnabledFor(tool.getComponent(), tool
467: .isEnabled());
468: }
469: }
470: }
471:
472: protected void setControls(List<SComponent> controls) {
473: controlBar.removeAll();
474:
475: if (controls != null) {
476: GridBagConstraints constraints = new GridBagConstraints();
477: constraints.weightx = .01;
478: constraints.gridwidth = 1;
479: constraints.insets = new Insets(0, 0, 0, 10);
480:
481: for (SComponent control : controls)
482: controlBar.add(control, constraints);
483:
484: constraints.weightx = 1.0 - controls.size() * .01;
485: controlBar.add(new SLabel("<html> "), constraints);
486: }
487: }
488:
489: protected void setTitle(String title) {
490: titleLabel.setText(title);
491: super .setTitle(title);
492: }
493:
494: protected void setContent(SComponent contentPane) {
495: if (shownComponent == contentPane)
496: return;
497:
498: if (shownComponent != null)
499: content.remove(shownComponent);
500:
501: if (contentPane != null) {
502: content.add(contentPane, SBorderLayout.CENTER);
503: contentPane.setVerticalAlignment(SConstants.TOP_ALIGN);
504: contentPane.setPreferredSize(SDimension.FULLAREA);
505: }
506:
507: shownComponent = contentPane;
508: }
509:
510: protected void setDefaultButton(SButton button) {
511: form.setDefaultButton(button);
512: }
513:
514: protected Window currentWindow(SComponent component) {
515: for (Stack<org.osbl.client.wings.shell.Window> stack : getWindowStacksModel()) {
516: for (Window window : stack) {
517: if (window.getContentPane() == component)
518: return window;
519: }
520: }
521: SContainer parent = component.getParent();
522: if (parent != null)
523: return currentWindow(parent);
524: else
525: return null;
526: }
527:
528: @Deprecated
529: public void show(String character, SComponent component) {
530: noWindow.show(component);
531: pushWindow(noWindow);
532:
533: /*
534: if (navigationsSideBar.isPinned() && navigationsSideBar.isVisible()) {
535: navigationsSideBar.show();
536: } else {
537: navigationsSideBar.hide();
538: }
539:
540: toolsSideBar.hide();
541: */
542: }
543:
544: @Deprecated
545: public void hide(String character, SComponent component) {
546: noWindow.hide(component);
547: }
548:
549: public SComponent getShownComponent() {
550: return shownComponent;
551: }
552:
553: @Deprecated
554: public void showMessage(Message message) {
555: noWindow.setStatusMessage(message);
556: }
557:
558: @Deprecated
559: public void showDetailHelp(String key) {
560: noWindow.showDetailHelp(key);
561: }
562:
563: @Deprecated
564: public void hideMessage(Message message) {
565: noWindow.setStatusMessage(null);
566: }
567:
568: @Deprecated
569: public void clearMessages() {
570: noWindow.setStatusMessage(null);
571: }
572:
573: @Deprecated
574: public void refreshTitle() {
575: noWindow.refreshTitle();
576: }
577:
578: @Deprecated
579: public void refreshActions() {
580: noWindow.refreshActions();
581: }
582:
583: @Deprecated
584: public void refreshTools() {
585: noWindow.refreshTools();
586: }
587:
588: public void setDevelopmentTool(DevelopmentTool developmentTool) {
589: super .setDevelopmentTool(developmentTool);
590: toolsSideBar.addTab((String) developmentTool
591: .getValue(Tool.NAME), developmentTool.getComponent());
592: }
593:
594: public void addHeaderComponent(SComponent component) {
595: if (headerPanel.getComponentCount() > 0)
596: headerPanel.add(new SLabel("<html> "));
597: headerPanel.add(component);
598: ((SGridLayout) headerPanel.getLayout()).setColumns(headerPanel
599: .getComponentCount());
600: }
601:
602: private class PrintAction extends AbstractAction {
603: public PrintAction() {
604: putValue(SMALL_ICON, new SURLIcon(
605: "../icon/16x16/printer2.png", 16, 16));
606: }
607:
608: public void actionPerformed(ActionEvent e) {
609: final SFrame frame = new SFrame();
610: String id = findResource(frame);
611: System.out.println("print frame id = " + id);
612:
613: JavaScriptListener listener = new JavaScriptListener(
614: "onload", null, "location.href='" + id + "'");
615: ProcessClient.this .frame.getSession().getScriptManager()
616: .addScriptListener(listener);
617:
618: frame.getContentPane().setLayout(new SBorderLayout());
619: frame.getContentPane().add(shownComponent,
620: SBorderLayout.CENTER);
621: SButton close = new SButton(Client.getInstance()
622: .getResourceProvider().getMessage(
623: "businessobject.buttons.back"));
624: close.addActionListener(new ActionListener() {
625: public void actionPerformed(ActionEvent e) {
626: show("", shownComponent);
627: String id = findResource(ProcessClient.this .frame);
628: System.out.println("process client frame id = "
629: + id);
630: JavaScriptListener listener = new JavaScriptListener(
631: "onload", null, "location.href='" + id
632: + "'");
633: frame.getSession().getScriptManager()
634: .addScriptListener(listener);
635: }
636: });
637: frame.getContentPane().add(close, SBorderLayout.SOUTH);
638: frame.setVisible(true);
639: }
640:
641: private String findResource(SFrame frame) {
642: String id = null;
643: Collection<DynamicResource> resources = frame
644: .getDynamicResources();
645: for (DynamicResource resource : resources) {
646: if ("CompleteUpdateResource".equals(resource.getClass()
647: .getSimpleName())
648: || "DynamicCodeResource".equals(resource
649: .getClass().getSimpleName())) {
650: id = resource.getId();
651: break;
652: }
653: }
654: if (id == null)
655: throw new IllegalStateException(
656: "What is the correct resource? .. " + resources);
657: return id;
658: }
659: }
660: }
|