2121import pixelitor .colors .FgBgColors ;
2222import pixelitor .gui .GlobalEvents ;
2323import pixelitor .gui .PixelitorWindow ;
24+ import pixelitor .gui .StatusBar ;
25+ import pixelitor .gui .WorkSpace ;
2426import pixelitor .gui .utils .TaskAction ;
2527import pixelitor .layers .AddTextLayerAction ;
2628import pixelitor .tools .Tool ;
3032import java .awt .BorderLayout ;
3133import java .awt .Dimension ;
3234import java .awt .event .ActionEvent ;
35+ import java .util .Collections ;
36+ import java .util .HashSet ;
37+ import java .util .List ;
38+ import java .util .Set ;
3339
3440/**
3541 * The panel with the tool buttons and the color selector
@@ -38,41 +44,69 @@ public class ToolsPanel extends JPanel {
3844 public ToolsPanel (PixelitorWindow pw , Dimension screenSize ) {
3945 Dimension buttonSize = calcToolButtonSize (screenSize , pw );
4046
41- // We need to give a hint to the layout manager, but at
42- // this point neither the panel nor the window size is known.
43- int heightHint = Math .max (screenSize .height - 168 , 0 );
47+ JComponent colorSelector = createColorSelector (pw );
48+ int heightHint = calcHeightHint (pw , colorSelector , buttonSize );
4449
4550 JPanel buttonsPanel = new JPanel (new ToolButtonsLayout (buttonSize .width , buttonSize .height , 0 , heightHint ));
4651 addToolButtons (buttonsPanel );
4752
4853 setLayout (new BorderLayout ());
4954 add (buttonsPanel , BorderLayout .CENTER );
50- addColorSelector ( pw );
55+ add ( colorSelector , BorderLayout . SOUTH );
5156
5257 setupTShortCut ();
5358 }
5459
55- private static void addToolButtons (JPanel toolsPanel ) {
60+ private static int calcHeightHint (PixelitorWindow pw , JComponent colorSelector , Dimension buttonSize ) {
61+ // get the preferred heights of all other components that take up vertical space.
62+ int menuBarHeight = pw .getJMenuBar ().getPreferredSize ().height ;
63+ WorkSpace workSpace = pw .getWorkSpace ();
64+ int toolSettingsHeight = workSpace .areToolsVisible () ? ToolSettingsPanelContainer .get ().getPreferredSize ().height : 0 ;
65+ int statusBarHeight = workSpace .isStatusBarVisible () ? StatusBar .get ().getPreferredSize ().height : 0 ;
66+ int colorSelectorHeight = colorSelector .getPreferredSize ().height ;
67+
68+ // the window's insets include the title bar
69+ int windowInsetsHeight = pw .getInsets ().top + pw .getInsets ().bottom ;
70+
71+ // sum of all vertical space NOT available to the buttons panel
72+ int totalOtherHeight = menuBarHeight + toolSettingsHeight + statusBarHeight + colorSelectorHeight + windowInsetsHeight ;
73+
74+ // the total window height minus all other components
75+ int heightHint = pw .getHeight () - totalOtherHeight ;
76+
77+ // ensure the hint is a positive value
78+ heightHint = Math .max (heightHint , buttonSize .height );
79+ return heightHint ;
80+ }
81+
82+ private static void addToolButtons (JPanel buttonContainer ) {
5683 ButtonGroup group = new ButtonGroup ();
57- Tool [] tools = Tools .getAll ();
58- for (Tool tool : tools ) {
84+
85+ List <Tool []> sharedHotkeyGroups = Tools .getSharedHotkeyGroups ();
86+ for (Tool [] toolGroup : sharedHotkeyGroups ) {
87+ setupSharedHotkey (toolGroup );
88+ }
89+
90+ Set <Tool > toolsWithSharedHotkeys = new HashSet <>();
91+ for (Tool [] toolGroup : sharedHotkeyGroups ) {
92+ Collections .addAll (toolsWithSharedHotkeys , toolGroup );
93+ }
94+
95+ for (Tool tool : Tools .getAll ()) {
5996 ToolButton toolButton = new ToolButton (tool );
60- toolsPanel .add (toolButton );
97+ buttonContainer .add (toolButton );
6198 group .add (toolButton );
62- if (!tool .hasSharedHotkey ()) {
99+
100+ if (!toolsWithSharedHotkeys .contains (tool )) {
63101 setupHotkey (tool );
64102 }
65103 }
66- // manually register the hotkeys of the sharing tools
67- setupSharedHotkey (Tools .RECTANGLE_SELECTION , Tools .ELLIPSE_SELECTION );
68- setupSharedHotkey (Tools .LASSO_SELECTION , Tools .POLY_SELECTION );
69- setupSharedHotkey (Tools .PEN , Tools .NODE , Tools .TRANSFORM_PATH );
70104 }
71105
72- private void addColorSelector (PixelitorWindow pw ) {
106+ private static JComponent createColorSelector (PixelitorWindow pw ) {
73107 FgBgColorSelector colorSelector = new FgBgColorSelector (pw );
74108 FgBgColors .setUI (colorSelector );
75- add ( colorSelector , BorderLayout . SOUTH ) ;
109+ return colorSelector ;
76110 }
77111
78112 private static void setupTShortCut () {
@@ -103,17 +137,17 @@ private static Dimension calcToolButtonSize(Dimension screen, PixelitorWindow pw
103137 }
104138
105139 private static void setupHotkey (Tool tool ) {
106- Action activateAction = new TaskAction (() -> {
140+ Action activateToolAction = new TaskAction (() -> {
107141 if (Tools .activeTool != tool ) {
108142 tool .activate ();
109143 }
110144 });
111145
112- GlobalEvents .registerHotkey (tool .getHotkey (), activateAction );
146+ GlobalEvents .registerHotkey (tool .getHotkey (), activateToolAction );
113147 }
114148
115149 private static void setupSharedHotkey (Tool ... sharingTools ) {
116- Action multiToolAction = new AbstractAction () {
150+ Action cycleToolsAction = new AbstractAction () {
117151 @ Override
118152 public void actionPerformed (ActionEvent e ) {
119153 int activeIndex = -1 ;
@@ -130,7 +164,8 @@ public void actionPerformed(ActionEvent e) {
130164 sharingTools [nextIndex ].activate ();
131165 }
132166 };
167+ // all tools in a group are expected to have the same hotkey
133168 char key = sharingTools [0 ].getHotkey ();
134- GlobalEvents .registerHotkey (key , multiToolAction );
169+ GlobalEvents .registerHotkey (key , cycleToolsAction );
135170 }
136171}
0 commit comments