View Javadoc
1   /*
2    * Tethys: GUI Utilities
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.tethys.core.pane;
18  
19  import io.github.tonywasher.joceanus.oceanus.event.OceanusEventManager;
20  import io.github.tonywasher.joceanus.oceanus.event.OceanusEventRegistrar;
21  import io.github.tonywasher.joceanus.tethys.api.base.TethysUIEvent;
22  import io.github.tonywasher.joceanus.tethys.api.pane.TethysUITabPaneManager;
23  import io.github.tonywasher.joceanus.tethys.core.base.TethysUICoreComponent;
24  import io.github.tonywasher.joceanus.tethys.core.factory.TethysUICoreFactory;
25  
26  /**
27   * Tab Manager.
28   */
29  public abstract class TethysUICoreTabPaneManager
30          extends TethysUICoreComponent
31          implements TethysUITabPaneManager {
32      /**
33       * The gui factory.
34       */
35      private final TethysUICoreFactory<?> theGuiFactory;
36  
37      /**
38       * The id.
39       */
40      private final Integer theId;
41  
42      /**
43       * The Event Manager.
44       */
45      private final OceanusEventManager<TethysUIEvent> theEventManager;
46  
47      /**
48       * The first child item.
49       */
50      private TethysUICoreTabItem theFirstChild;
51  
52      /**
53       * The last child item.
54       */
55      private TethysUICoreTabItem theLastChild;
56  
57      /**
58       * Is the pane enabled?
59       */
60      private boolean isEnabled;
61  
62      /**
63       * Constructor.
64       *
65       * @param pFactory the factory
66       */
67      protected TethysUICoreTabPaneManager(final TethysUICoreFactory<?> pFactory) {
68          theGuiFactory = pFactory;
69          theId = pFactory.getNextId();
70          theEventManager = new OceanusEventManager<>();
71          isEnabled = true;
72      }
73  
74      @Override
75      public Integer getId() {
76          return theId;
77      }
78  
79      @Override
80      public OceanusEventRegistrar<TethysUIEvent> getEventRegistrar() {
81          return theEventManager.getEventRegistrar();
82      }
83  
84      @Override
85      public TethysUICoreTabItem findItemByName(final String pName) {
86          /* loop through children */
87          TethysUICoreTabItem myChild = theFirstChild;
88          while (myChild != null) {
89              /* Break if we have found the item */
90              if (myChild.getName().equals(pName)) {
91                  break;
92              }
93  
94              /* Move to next child */
95              myChild = myChild.theNextSibling;
96          }
97  
98          /* return the relevant child */
99          return myChild;
100     }
101 
102     @Override
103     public TethysUICoreTabItem findItemByIndex(final int pIndex) {
104         /* loop through children */
105         TethysUICoreTabItem myChild = theFirstChild;
106         int myIndex = 0;
107         while (myChild != null) {
108             /* If the child is visible */
109             if (myChild.isVisible()) {
110                 /* If this is the required index */
111                 if (pIndex == myIndex) {
112                     break;
113                 }
114                 myIndex++;
115             }
116 
117             /* Move to next child */
118             myChild = myChild.theNextSibling;
119         }
120 
121         /* return the relevant child */
122         return myChild;
123     }
124 
125     @Override
126     public void enableItemByName(final String pName,
127                                  final boolean pEnabled) {
128         /* Look up child and adjust */
129         final TethysUICoreTabItem myItem = findItemByName(pName);
130         if (myItem != null) {
131             myItem.setEnabled(pEnabled);
132         }
133     }
134 
135     /**
136      * Notify of selection.
137      *
138      * @param pItem the item that has been selected
139      */
140     protected void notifySelection(final Object pItem) {
141         theEventManager.fireEvent(TethysUIEvent.NEWVALUE, pItem);
142     }
143 
144     @Override
145     public void setEnabled(final boolean pEnabled) {
146         /* If we are changing enabled state */
147         if (pEnabled != isEnabled) {
148             /* Set new enabled state */
149             isEnabled = pEnabled;
150 
151             /* enable the tab */
152             enablePane(isEnabled);
153 
154             /* loop through children */
155             TethysUICoreTabItem myChild = theFirstChild;
156             while (myChild != null) {
157                 /* If the child is visible */
158                 if (myChild.isVisible()) {
159                     /* set correct enabled status */
160                     myChild.enableTab(pEnabled
161                             && myChild.isEnabled());
162                 }
163 
164                 /* Move to next child */
165                 myChild = myChild.theNextSibling;
166             }
167         }
168     }
169 
170     /**
171      * Enable/disable the pane.
172      *
173      * @param pEnabled true/false
174      */
175     protected abstract void enablePane(boolean pEnabled);
176 
177     /**
178      * TabItem class.
179      */
180     public abstract static class TethysUICoreTabItem
181             implements TethysUITabItem {
182         /**
183          * The pane to which this item belongs.
184          */
185         private final TethysUICoreTabPaneManager thePane;
186 
187         /**
188          * The name of this item.
189          */
190         private final String theName;
191 
192         /**
193          * The id of this item.
194          */
195         private final Integer theId;
196 
197         /**
198          * The previous sibling of this item.
199          */
200         private TethysUICoreTabItem thePrevSibling;
201 
202         /**
203          * The next sibling of this item.
204          */
205         private TethysUICoreTabItem theNextSibling;
206 
207         /**
208          * Is the item visible (i.e. part of the actual tabs)?
209          */
210         private boolean isVisible;
211 
212         /**
213          * Is the item enabled?
214          */
215         private boolean isEnabled;
216 
217         /**
218          * Constructor.
219          *
220          * @param pPane the containing pane
221          * @param pName the name of the tab
222          */
223         protected TethysUICoreTabItem(final TethysUICoreTabPaneManager pPane,
224                                       final String pName) {
225             /* Store parameters */
226             thePane = pPane;
227             theName = pName;
228             isVisible = true;
229             isEnabled = true;
230 
231             /* Create id */
232             theId = pPane.theGuiFactory.getNextId();
233 
234             /* If the pane already has children */
235             final TethysUICoreTabItem myChild = thePane.theLastChild;
236             if (myChild != null) {
237                 /* Link to last child */
238                 myChild.theNextSibling = this;
239                 thePrevSibling = myChild;
240 
241                 /* else set as first child */
242             } else {
243                 thePane.theFirstChild = this;
244             }
245 
246             /* Add as last child of pane */
247             thePane.theLastChild = this;
248         }
249 
250         @Override
251         public String getName() {
252             return theName;
253         }
254 
255         @Override
256         public Integer getId() {
257             return theId;
258         }
259 
260         @Override
261         public TethysUICoreTabPaneManager getPane() {
262             return thePane;
263         }
264 
265         @Override
266         public boolean isVisible() {
267             return isVisible;
268         }
269 
270         @Override
271         public boolean isEnabled() {
272             return isEnabled;
273         }
274 
275         @Override
276         public void setVisible(final boolean pVisible) {
277             /* If we are changing visibility */
278             if (pVisible != isVisible) {
279                 /* Set new visibility */
280                 isVisible = pVisible;
281 
282                 /* If we are showing the item */
283                 if (pVisible) {
284                     /* Attach to parent at required position */
285                     attachToPane();
286 
287                     /* make sure that we have correct enable state */
288                     enableTab(isEnabled);
289 
290                     /* else just detach item */
291                 } else {
292                     detachFromPane();
293                 }
294             }
295         }
296 
297         @Override
298         public void setEnabled(final boolean pEnabled) {
299             /* If we are changing enabled state */
300             if (pEnabled != isEnabled) {
301                 /* Set new enabled state */
302                 isEnabled = pEnabled;
303 
304                 /* If the pane is enabled and the tab is visible */
305                 if (thePane.isEnabled
306                         && isVisible) {
307                     /* enable the tab */
308                     enableTab(isEnabled);
309                 }
310             }
311         }
312 
313         /**
314          * Enable/disable the tab.
315          *
316          * @param pEnabled true/false
317          */
318         protected abstract void enableTab(boolean pEnabled);
319 
320         /**
321          * Attach to pane.
322          */
323         protected abstract void attachToPane();
324 
325         /**
326          * Detach from pane.
327          */
328         protected abstract void detachFromPane();
329 
330         /**
331          * Notify of selection.
332          */
333         protected void notifySelection() {
334             getPane().notifySelection(this);
335         }
336 
337         /**
338          * Count previous visible items.
339          *
340          * @return the count
341          */
342         public int countPreviousVisibleSiblings() {
343             /* Determine the previous visible sibling */
344             int myCount = 0;
345             TethysUICoreTabItem mySibling = thePrevSibling;
346             while (mySibling != null) {
347                 if (mySibling.isVisible) {
348                     myCount++;
349                 }
350                 mySibling = mySibling.thePrevSibling;
351             }
352             return myCount;
353         }
354     }
355 }