001 package org.springframework.richclient.command;
002
003 import org.springframework.richclient.application.Application;
004 import org.springframework.richclient.command.config.CommandButtonConfigurer;
005 import org.springframework.richclient.command.config.CommandConfigurer;
006 import org.springframework.richclient.factory.ButtonFactory;
007
008 import javax.swing.*;
009 import java.beans.PropertyChangeListener;
010 import java.beans.PropertyChangeEvent;
011 import java.awt.event.ComponentAdapter;
012 import java.awt.event.ComponentEvent;
013 import java.awt.*;
014
015 public class SplitPaneExpansionToggleCommand extends ActionCommand
016 {
017
018 private DefaultButtonModel model;
019
020 public SplitPaneExpansionToggleCommand(String commandId, JSplitPane splitPane, boolean switchedAway)
021 {
022 super(commandId);
023 this.model = new SplitPaneExpansionButtonModel(splitPane, switchedAway);
024 ((CommandConfigurer) Application.services().getService(CommandConfigurer.class)).configure(this);
025 }
026
027
028 protected void doExecuteCommand()
029 {
030 //toggle
031 this.model.setSelected(!this.model.isSelected());
032
033 }
034
035 public void doHide()
036 {
037 this.model.setSelected(false);
038 }
039
040 public void doShow()
041 {
042 this.model.setSelected(true);
043 }
044
045 public AbstractButton createButton(String faceDescriptorId, ButtonFactory buttonFactory,
046 CommandButtonConfigurer configurer)
047 {
048 AbstractButton button = buttonFactory.createToggleButton();
049 attach(button, faceDescriptorId, configurer);
050 return button;
051 }
052
053 public void attach(AbstractButton button, String faceDescriptorId,
054 CommandButtonConfigurer configurer)
055 {
056 super.attach(button, faceDescriptorId, configurer);
057 button.setModel(this.model);
058 }
059
060 public static class SplitPaneExpansionButtonModel extends DefaultButtonModel
061 {
062
063 private final JSplitPane splitPane;
064
065 private enum SWITCH_STATE
066 {
067 NO_ACTION, SWITCHED_AWAY, SWITCHED_AWAY_AND_MOVED
068 }
069
070 ;
071
072 private SWITCH_STATE state = SWITCH_STATE.NO_ACTION;
073
074 private transient PropertyChangeListener listener = new PropertyChangeListener()
075 {
076 public void propertyChange(PropertyChangeEvent evt)
077 {
078 fireStateChanged();
079
080 if (state == SWITCH_STATE.SWITCHED_AWAY)
081 state = SWITCH_STATE.SWITCHED_AWAY_AND_MOVED;
082 else if (state == SWITCH_STATE.SWITCHED_AWAY_AND_MOVED)
083 state = SWITCH_STATE.NO_ACTION;
084 }
085 };
086
087 public SplitPaneExpansionButtonModel(JSplitPane mySplitPane, boolean switchedAway)
088 {
089 super();
090 this.splitPane = mySplitPane;
091
092 this.splitPane.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY,
093 listener);
094
095 this.splitPane.addComponentListener(new ComponentAdapter()
096 {
097 @Override
098 public void componentResized(ComponentEvent e)
099 {
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); // we need to correct with the border size
146 int dividerSize = splitPane.getDividerSize();// we need to correct with the size of the divider!
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) ? // for vertical
154 (insets.bottom) : //take the height
155 (insets.right); // else the width
156 return result;
157 }
158
159 private int getRelevantDimensionpart(Dimension size)
160 {
161 int orientation = splitPane.getOrientation();
162 int result = (orientation == JSplitPane.VERTICAL_SPLIT) ? // for vertical
163 (int) Math.ceil(size.getHeight()) : //take the height
164 (int) Math.ceil(size.getWidth()); // else the width
165 return result;
166 }
167 }
168
169 }
170