View Javadoc
1   /*
2    * Metis: Java Data Framework
3    * Copyright 2012-2026. Tony Washer
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6    * use this file except in compliance with the License.  You may obtain a copy
7    * of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
14   * License for the specific language governing permissions and limitations under
15   * the License.
16   */
17  package io.github.tonywasher.joceanus.metis.viewer;
18  
19  import io.github.tonywasher.joceanus.tethys.api.base.TethysUIComponent;
20  import io.github.tonywasher.joceanus.tethys.api.base.TethysUIEvent;
21  import io.github.tonywasher.joceanus.tethys.api.base.TethysUIIconId;
22  import io.github.tonywasher.joceanus.tethys.api.button.TethysUIButton;
23  import io.github.tonywasher.joceanus.tethys.api.button.TethysUIButtonFactory;
24  import io.github.tonywasher.joceanus.tethys.api.button.TethysUIScrollButtonManager;
25  import io.github.tonywasher.joceanus.tethys.api.control.TethysUIControlFactory;
26  import io.github.tonywasher.joceanus.tethys.api.control.TethysUILabel;
27  import io.github.tonywasher.joceanus.tethys.api.control.TethysUISlider;
28  import io.github.tonywasher.joceanus.tethys.api.factory.TethysUIFactory;
29  import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollMenu;
30  import io.github.tonywasher.joceanus.tethys.api.pane.TethysUIBorderPaneManager;
31  import io.github.tonywasher.joceanus.tethys.api.pane.TethysUIBoxPaneManager;
32  import io.github.tonywasher.joceanus.tethys.api.pane.TethysUIPaneFactory;
33  
34  /**
35   * Viewer Control bar.
36   */
37  public class MetisViewerControl
38          implements TethysUIComponent {
39      /**
40       * The item text.
41       */
42      private static final String TEXT_ITEM = MetisViewerResource.VIEWER_SELECT_ITEM.getValue();
43  
44      /**
45       * The of text.
46       */
47      private static final String TEXT_OF = MetisViewerResource.VIEWER_SELECT_OF.getValue();
48  
49      /**
50       * Blank character.
51       */
52      private static final char CHAR_BLANK = ' ';
53  
54      /**
55       * Default icon size.
56       */
57      private static final int ICON_SIZE = 24;
58  
59      /**
60       * The HGap.
61       */
62      private static final int HGAP_SIZE = 10;
63  
64      /**
65       * The panel.
66       */
67      private final TethysUIBorderPaneManager thePane;
68  
69      /**
70       * The viewer.
71       */
72      private final MetisViewerWindow theViewer;
73  
74      /**
75       * The parent button.
76       */
77      private final TethysUIButton theParentButton;
78  
79      /**
80       * The mode button.
81       */
82      private final TethysUIScrollButtonManager<MetisViewerMode> theModeButton;
83  
84      /**
85       * The next button.
86       */
87      private final TethysUIButton theNextButton;
88  
89      /**
90       * The previous button.
91       */
92      private final TethysUIButton thePrevButton;
93  
94      /**
95       * The label.
96       */
97      private final TethysUILabel theLabel;
98  
99      /**
100      * The slider.
101      */
102     private final TethysUISlider theSlider;
103 
104     /**
105      * The slider panel.
106      */
107     private final TethysUIBorderPaneManager theSliderPane;
108 
109     /**
110      * The buttons panel.
111      */
112     private final TethysUIBoxPaneManager theButtonsPane;
113 
114     /**
115      * Constructor.
116      *
117      * @param pFactory the GuiFactory
118      * @param pViewer  the viewer window
119      */
120     protected MetisViewerControl(final TethysUIFactory<?> pFactory,
121                                  final MetisViewerWindow pViewer) {
122         /* Store parameters */
123         theViewer = pViewer;
124 
125         /* Create the parent button */
126         final TethysUIButtonFactory<?> myButtons = pFactory.buttonFactory();
127         theParentButton = myButtons.newButton();
128         configureButton(theParentButton, MetisViewerIcon.PARENT);
129         theParentButton.getEventRegistrar().addEventListener(e -> theViewer.handleParentPage());
130 
131         /* Create the mode button */
132         theModeButton = myButtons.newScrollButton(MetisViewerMode.class);
133         theModeButton.getEventRegistrar().addEventListener(TethysUIEvent.NEWVALUE, e -> theViewer.handleMode(theModeButton.getValue()));
134 
135         /* Create the next button */
136         theNextButton = myButtons.newButton();
137         configureButton(theNextButton, MetisViewerIcon.NEXT);
138         theNextButton.getEventRegistrar().addEventListener(e -> theViewer.handleNextPage());
139 
140         /* Create the previous button */
141         thePrevButton = myButtons.newButton();
142         configureButton(thePrevButton, MetisViewerIcon.PREV);
143         thePrevButton.getEventRegistrar().addEventListener(e -> theViewer.handlePreviousPage());
144 
145         /* Create the label */
146         final TethysUIControlFactory myControls = pFactory.controlFactory();
147         theLabel = myControls.newLabel();
148 
149         /* Create the slider */
150         theSlider = myControls.newSlider();
151         theSlider.getEventRegistrar().addEventListener(e -> theViewer.handleExplicitPage(theSlider.getValue() + 1));
152 
153         /* Create the Inner Slider Pane */
154         final TethysUIPaneFactory myPanes = pFactory.paneFactory();
155         final TethysUIBorderPaneManager myInnerPane = myPanes.newBorderPane();
156         myInnerPane.setCentre(theSlider);
157         myInnerPane.setEast(theNextButton);
158         myInnerPane.setWest(thePrevButton);
159 
160         /* Create the true Slider Pane */
161         theSliderPane = myPanes.newBorderPane();
162         theSliderPane.setHGap(HGAP_SIZE);
163         theSliderPane.setCentre(myInnerPane);
164         theSliderPane.setWest(theLabel);
165 
166         /* Create the Buttons Pane */
167         theButtonsPane = myPanes.newHBoxPane();
168         theButtonsPane.addNode(theParentButton);
169         theButtonsPane.addNode(theModeButton);
170 
171         /* Create the Main Pane */
172         thePane = myPanes.newBorderPane();
173         thePane.setCentre(theSliderPane);
174         thePane.setWest(theButtonsPane);
175         setVisible(false);
176     }
177 
178     @Override
179     public TethysUIComponent getUnderlying() {
180         return thePane;
181     }
182 
183     /**
184      * Configure button.
185      *
186      * @param <K>     the key type
187      * @param pButton the button
188      * @param pId     the icon id
189      */
190     private static <K extends Enum<K> & TethysUIIconId> void configureButton(final TethysUIButton pButton,
191                                                                              final K pId) {
192         pButton.setIconOnly();
193         pButton.setIcon(pId);
194         pButton.setIconSize(ICON_SIZE);
195         pButton.setNullMargins();
196     }
197 
198     /**
199      * Update the state according to the page.
200      *
201      * @param pPage the ViewerPage
202      */
203     protected void updateState(final MetisViewerPage pPage) {
204         /* Only show Parent button if we have a parent */
205         final boolean hasParent = pPage.hasParent();
206         theParentButton.setVisible(hasParent);
207         boolean isVisible = hasParent;
208 
209         /* Set the active mode */
210         final MetisViewerMode myMode = pPage.getMode();
211         final boolean isList = !MetisViewerMode.CONTENTS.equals(myMode);
212 
213         /* Set the Mode Button */
214         theModeButton.setValue(myMode);
215         final boolean isEnabled = pPage.hasMultiModes();
216         theModeButton.setEnabled(isEnabled);
217         if (isEnabled) {
218             buildModeMenu(pPage);
219         }
220         isVisible |= isEnabled;
221 
222         /* Obtain list details */
223         final int mySize = pPage.getSize();
224         final int myPos = pPage.getItemNo();
225 
226         /* If we are a list */
227         if (isList
228                 && (mySize > 1)) {
229             /* Show the Slider */
230             theSliderPane.setVisible(true);
231             isVisible = true;
232 
233             /* Build the text */
234             final String myText = TEXT_ITEM
235                     + CHAR_BLANK
236                     + myPos
237                     + CHAR_BLANK
238                     + TEXT_OF
239                     + CHAR_BLANK
240                     + mySize;
241             theLabel.setText(myText);
242 
243             /* Configure the slider */
244             theSlider.setMaximum(mySize - 1);
245             theSlider.setValue(myPos - 1);
246 
247             /* Disable next/previous as necessary */
248             theNextButton.setEnabled(pPage.hasNext());
249             thePrevButton.setEnabled(pPage.hasPrevious());
250 
251             /* else not a list mode */
252         } else {
253             /* Hide the Slider */
254             theSliderPane.setVisible(false);
255         }
256 
257         /* Set visibility */
258         setVisible(isVisible);
259     }
260 
261     /**
262      * Build the mode menu.
263      *
264      * @param pPage the ViewerPage
265      */
266     private void buildModeMenu(final MetisViewerPage pPage) {
267         /* Access the menu and reset it */
268         final TethysUIScrollMenu<MetisViewerMode> myMenu = theModeButton.getMenu();
269         myMenu.removeAllItems();
270 
271         /* Loop through the modes */
272         for (MetisViewerMode myMode : MetisViewerMode.values()) {
273             /* If this is a valid mode */
274             if (pPage.validMode(myMode)) {
275                 /* Add to menu */
276                 myMenu.addItem(myMode);
277             }
278         }
279     }
280 }