1 package org.springframework.richclient.command;
2
3 import org.springframework.richclient.application.Application;
4 import org.springframework.richclient.command.config.CommandButtonConfigurer;
5 import org.springframework.richclient.command.config.CommandConfigurer;
6 import org.springframework.richclient.factory.ButtonFactory;
7
8 import javax.swing.*;
9 import java.beans.PropertyChangeListener;
10 import java.beans.PropertyChangeEvent;
11 import java.awt.event.ComponentAdapter;
12 import java.awt.event.ComponentEvent;
13 import java.awt.*;
14
15 public class SplitPaneExpansionToggleCommand extends ActionCommand
16 {
17
18 private DefaultButtonModel model;
19
20 public SplitPaneExpansionToggleCommand(String commandId, JSplitPane splitPane, boolean switchedAway)
21 {
22 super(commandId);
23 this.model = new SplitPaneExpansionButtonModel(splitPane, switchedAway);
24 ((CommandConfigurer) Application.services().getService(CommandConfigurer.class)).configure(this);
25 }
26
27
28 protected void doExecuteCommand()
29 {
30
31 this.model.setSelected(!this.model.isSelected());
32
33 }
34
35 public void doHide()
36 {
37 this.model.setSelected(false);
38 }
39
40 public void doShow()
41 {
42 this.model.setSelected(true);
43 }
44
45 public AbstractButton createButton(String faceDescriptorId, ButtonFactory buttonFactory,
46 CommandButtonConfigurer configurer)
47 {
48 AbstractButton button = buttonFactory.createToggleButton();
49 attach(button, faceDescriptorId, configurer);
50 return button;
51 }
52
53 public void attach(AbstractButton button, String faceDescriptorId,
54 CommandButtonConfigurer configurer)
55 {
56 super.attach(button, faceDescriptorId, configurer);
57 button.setModel(this.model);
58 }
59
60 public static class SplitPaneExpansionButtonModel extends DefaultButtonModel
61 {
62
63 private final JSplitPane splitPane;
64
65 private enum SWITCH_STATE
66 {
67 NO_ACTION, SWITCHED_AWAY, SWITCHED_AWAY_AND_MOVED
68 }
69
70 ;
71
72 private SWITCH_STATE state = SWITCH_STATE.NO_ACTION;
73
74 private transient PropertyChangeListener listener = new PropertyChangeListener()
75 {
76 public void propertyChange(PropertyChangeEvent evt)
77 {
78 fireStateChanged();
79
80 if (state == SWITCH_STATE.SWITCHED_AWAY)
81 state = SWITCH_STATE.SWITCHED_AWAY_AND_MOVED;
82 else if (state == SWITCH_STATE.SWITCHED_AWAY_AND_MOVED)
83 state = SWITCH_STATE.NO_ACTION;
84 }
85 };
86
87 public SplitPaneExpansionButtonModel(JSplitPane mySplitPane, boolean switchedAway)
88 {
89 super();
90 this.splitPane = mySplitPane;
91
92 this.splitPane.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY,
93 listener);
94
95 this.splitPane.addComponentListener(new ComponentAdapter()
96 {
97 @Override
98 public void componentResized(ComponentEvent e)
99 {
100 if (state == SWITCH_STATE.SWITCHED_AWAY || state == SWITCH_STATE.SWITCHED_AWAY_AND_MOVED)
101 hidePanel();
102 }
103
104 });
105
106 if (switchedAway)
107 this.state = SWITCH_STATE.SWITCHED_AWAY;
108 }
109
110 public boolean isSelected()
111 {
112 return isShown();
113 }
114
115 public void setSelected(boolean makeVisible)
116 {
117 super.setSelected(makeVisible);
118 if (makeVisible)
119 {
120 splitPane.resetToPreferredSizes();
121 state = SWITCH_STATE.NO_ACTION;
122 }
123 else
124 {
125 hidePanel();
126 }
127 }
128
129 private void hidePanel()
130 {
131 splitPane.setDividerLocation(getHideRightComponentDividerLocation());
132 state = SWITCH_STATE.SWITCHED_AWAY;
133 }
134
135 private boolean isShown()
136 {
137 return splitPane.getDividerLocation() < (getHideRightComponentDividerLocation());
138 }
139
140 private int getHideRightComponentDividerLocation()
141 {
142 Dimension size = splitPane.getSize();
143 int max = getRelevantDimensionpart(size);
144 Insets insets = splitPane.getInsets();
145 int relevantInset = getRelevantInsetpart(insets);
146 int dividerSize = splitPane.getDividerSize();
147 return max - (relevantInset + dividerSize);
148 }
149
150 private int getRelevantInsetpart(Insets insets)
151 {
152 int orientation = splitPane.getOrientation();
153 int result = (orientation == JSplitPane.VERTICAL_SPLIT) ?
154 (insets.bottom) :
155 (insets.right);
156 return result;
157 }
158
159 private int getRelevantDimensionpart(Dimension size)
160 {
161 int orientation = splitPane.getOrientation();
162 int result = (orientation == JSplitPane.VERTICAL_SPLIT) ?
163 (int) Math.ceil(size.getHeight()) :
164 (int) Math.ceil(size.getWidth());
165 return result;
166 }
167 }
168
169 }
170