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.swing.field;
18  
19  import io.github.tonywasher.joceanus.oceanus.event.OceanusEvent;
20  import io.github.tonywasher.joceanus.tethys.api.base.TethysUIEvent;
21  import io.github.tonywasher.joceanus.tethys.api.button.TethysUIScrollButtonManager;
22  import io.github.tonywasher.joceanus.tethys.api.field.TethysUIDataEditField.TethysUIScrollButtonField;
23  import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollMenu;
24  import io.github.tonywasher.joceanus.tethys.core.factory.TethysUICoreFactory;
25  import io.github.tonywasher.joceanus.tethys.swing.base.TethysUISwingNode;
26  import io.github.tonywasher.joceanus.tethys.swing.button.TethysUISwingScrollButtonManager;
27  import io.github.tonywasher.joceanus.tethys.swing.menu.TethysUISwingScrollMenu;
28  
29  import javax.swing.JButton;
30  import javax.swing.JLabel;
31  import javax.swing.SwingConstants;
32  import java.awt.Rectangle;
33  import java.util.function.Consumer;
34  
35  /**
36   * ScrollButtonField class.
37   *
38   * @param <T> the data type
39   */
40  public final class TethysUISwingScrollButtonField<T>
41          extends TethysUISwingDataTextField<T>
42          implements TethysUIScrollButtonField<T> {
43      /**
44       * The scroll manager.
45       */
46      private final TethysUISwingScrollButtonManager<T> theManager;
47  
48      /**
49       * The configurator.
50       */
51      private Consumer<TethysUIScrollMenu<T>> theConfigurator;
52  
53      /**
54       * The button.
55       */
56      private final JButton theButton;
57  
58      /**
59       * Are we editing a cell?
60       */
61      private boolean isCellEditing;
62  
63      /**
64       * Constructor.
65       *
66       * @param pFactory the GUI factory
67       * @param pClazz   the value class
68       */
69      TethysUISwingScrollButtonField(final TethysUICoreFactory<?> pFactory,
70                                     final Class<T> pClazz) {
71          this(pFactory, pClazz, new JLabel());
72      }
73  
74      /**
75       * Constructor.
76       *
77       * @param pFactory the GUI factory
78       * @param pClazz   the value class
79       * @param pLabel   the label
80       */
81      private TethysUISwingScrollButtonField(final TethysUICoreFactory<?> pFactory,
82                                             final Class<T> pClazz,
83                                             final JLabel pLabel) {
84          this(pFactory, pFactory.buttonFactory().newScrollButton(pClazz), pLabel);
85      }
86  
87      /**
88       * Constructor.
89       *
90       * @param pFactory the GUI factory
91       * @param pManager the manager
92       * @param pLabel   the label
93       */
94      private TethysUISwingScrollButtonField(final TethysUICoreFactory<?> pFactory,
95                                             final TethysUIScrollButtonManager<T> pManager,
96                                             final JLabel pLabel) {
97          /* Initialise underlying class */
98          super(pFactory, TethysUISwingNode.getComponent(pManager), pLabel);
99  
100         /* Store the manager and button */
101         theManager = (TethysUISwingScrollButtonManager<T>) pManager;
102         theButton = getEditControl();
103 
104         /* Set listener on manager */
105         pManager.getEventRegistrar().addEventListener(this::handleEvent);
106         theManager.getMenu().getEventRegistrar().addEventListener(TethysUIEvent.WINDOWCLOSED, e -> haltCellEditing());
107 
108         /* Set configurator */
109         theConfigurator = p -> {
110         };
111     }
112 
113     @Override
114     public T getCastValue(final Object pValue) {
115         return theManager.getValueClass().cast(pValue);
116     }
117 
118     /**
119      * handle Scroll Button event.
120      *
121      * @param pEvent the even
122      */
123     private void handleEvent(final OceanusEvent<TethysUIEvent> pEvent) {
124         switch (pEvent.getEventId()) {
125             case NEWVALUE:
126                 setValue(theManager.getValue());
127                 fireEvent(TethysUIEvent.NEWVALUE, pEvent.getDetails());
128                 break;
129             case EDITFOCUSLOST:
130                 haltCellEditing();
131                 break;
132             default:
133                 break;
134         }
135     }
136 
137     @Override
138     public void setMenuConfigurator(final Consumer<TethysUIScrollMenu<T>> pConfigurator) {
139         theConfigurator = pConfigurator;
140         theManager.setMenuConfigurator(theConfigurator);
141     }
142 
143     @Override
144     public JButton getEditControl() {
145         return (JButton) super.getEditControl();
146     }
147 
148     @Override
149     public void setValue(final T pValue) {
150         /* Store the value */
151         super.setValue(pValue);
152 
153         /* Declare value to the manager */
154         theManager.setValue(pValue);
155         getLabel().setText(theButton.getText());
156     }
157 
158     @Override
159     public void startCellEditing(final Rectangle pCell) {
160         isCellEditing = true;
161         final TethysUISwingScrollMenu<T> myMenu = theManager.getMenu();
162         theConfigurator.accept(myMenu);
163         if (!myMenu.isEmpty()) {
164             myMenu.showMenuAtPosition(pCell, SwingConstants.BOTTOM);
165         } else {
166             haltCellEditing();
167         }
168     }
169 
170     /**
171      * haltCellEditing.
172      */
173     private void haltCellEditing() {
174         if (isCellEditing) {
175             fireEvent(TethysUIEvent.EDITFOCUSLOST, this);
176         }
177         isCellEditing = false;
178     }
179 
180     @Override
181     public TethysUISwingScrollButtonField<T> cloneField(final JLabel pLabel) {
182         return new TethysUISwingScrollButtonField<>(getGuiFactory(), theManager.getValueClass(), pLabel);
183     }
184 }