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