source: trunk/src/org/expeditee/items/widgets/SwingWidget.java

Last change on this file was 1561, checked in by davidb, 3 years ago

A set of changes that spans three things: beat detection, time stretching; and a debug class motivated by the need to look at a canvas redraw issue most notable when a waveform widget is playing

File size: 7.6 KB
Line 
1package org.expeditee.items.widgets;
2
3import java.awt.Component;
4import java.awt.Container;
5import java.awt.Graphics2D;
6import java.awt.Point;
7import java.awt.Rectangle;
8import java.awt.event.ContainerEvent;
9import java.awt.event.ContainerListener;
10import java.awt.event.KeyEvent;
11import java.awt.event.KeyListener;
12import java.util.Arrays;
13import java.util.LinkedList;
14import java.util.List;
15
16import javax.swing.JComponent;
17import javax.swing.JPopupMenu;
18
19import org.expeditee.core.bounds.AxisAlignedBoxBounds;
20import org.expeditee.gio.EcosystemManager;
21import org.expeditee.gio.EcosystemManager.Ecosystem;
22import org.expeditee.gio.swing.SwingGraphicsManager;
23import org.expeditee.gio.swing.SwingMiscManager;
24import org.expeditee.gui.DisplayController;
25import org.expeditee.items.ItemParentStateChangedEvent;
26import org.expeditee.items.Text;
27import org.expeditee.items.UserAppliedPermission;
28
29public abstract class SwingWidget extends Widget implements ContainerListener, KeyListener
30{
31 // A flag for signifying whether the swing components are ready to paint.
32 // If the swing components has not been layed out, if they are painted they
33 // will not draw in the correct positions.
34 // Also for setting AWT and Swing -Related drawing options after
35 // construction
36 private boolean _isReadyToPaint = false;
37
38 protected JComponent _swingComponent;
39
40 protected SwingWidget(Text source, JComponent component, int minWidth, int maxWidth, int minHeight, int maxHeight)
41 {
42 super(source, minWidth, maxWidth, minHeight, maxHeight);
43
44 if (component == null) {
45 throw new NullPointerException("component");
46 }
47
48 _swingComponent = component;
49 _swingComponent.setFocusable(true);
50 addKeyListenerToWidget();
51 addThisAsContainerListenerToContent();
52 onBoundsChanged();
53
54 System.err.println("SwingWidget::Suppressed static setDefaultLightWeightPopupEnabled to false.");
55 //JPopupMenu.setDefaultLightWeightPopupEnabled(false);
56 }
57
58 public JComponent getComponent()
59 {
60 return _swingComponent;
61 }
62
63 @Override
64 public void keyTyped(KeyEvent e) {
65
66 int keyCode = e.getKeyCode();
67
68 if (keyCode >= KeyEvent.VK_F1 && keyCode <= KeyEvent.VK_F12) {
69 //((SwingInputManager) EcosystemManager.getInputManager()).keyTyped(e);
70 }
71 }
72
73 @Override
74 public void keyPressed(KeyEvent e) {
75 int keyCode = e.getKeyCode();
76
77 if (keyCode >= KeyEvent.VK_F1 && keyCode <= KeyEvent.VK_F12) {
78 //((SwingInputManager) EcosystemManager.getInputManager()).keyTyped(e);
79 }
80 }
81
82 @Override
83 public void keyReleased(KeyEvent e) {
84 int keyCode = e.getKeyCode();
85
86 if (keyCode >= KeyEvent.VK_F1 && keyCode <= KeyEvent.VK_F12) {
87 //((SwingInputManager) EcosystemManager.getInputManager()).keyTyped(e);
88 }
89 }
90
91 /**
92 * Makes sure we add our KeyListener to every child component,
93 * since it seems that's the only way to make sure we capture key events in Java
94 * (without using KeyBindings which seem to only support the keyTyped event)
95 */
96 @Override
97 public void componentAdded(ContainerEvent e) {
98 if(e == null || e.getChild() == null) {
99 return;
100 }
101 keyListenerToChildren(e.getChild(), true);
102 }
103
104 @Override
105 public void componentRemoved(ContainerEvent e) {
106 if(e == null || e.getChild() == null) {
107 return;
108 }
109 keyListenerToChildren(e.getChild(), false);
110 }
111
112 @Override
113 protected void addWidgetContent(final ItemParentStateChangedEvent e) {
114 if ((e.getEventType() == ItemParentStateChangedEvent.EVENT_TYPE_ADDED_VIA_OVERLAY || e
115 .getEventType() == ItemParentStateChangedEvent.EVENT_TYPE_SHOWN_VIA_OVERLAY)
116 && e.getOverlayLevel().equals(UserAppliedPermission.none)) {
117 return; // item belongs to a non-active overlay
118 }
119
120 if(_swingComponent.getParent() == null) {
121 if (e.getEventType() == ItemParentStateChangedEvent.EVENT_TYPE_SHOWN
122 || e.getEventType() == ItemParentStateChangedEvent.EVENT_TYPE_SHOWN_VIA_OVERLAY
123 || e.getSource() == DisplayController.getCurrentFrame()) {
124 onBoundsChanged();
125 ((SwingGraphicsManager) EcosystemManager.getGraphicsManager()).getContentPane().add(_swingComponent);
126 layout(_swingComponent);
127 }
128 }
129 }
130
131 @Override
132 protected void addKeyListenerToWidget() {
133 keyListenerToChildren(_swingComponent, true);
134 }
135
136 @Override
137 protected void addThisAsContainerListenerToContent() {
138 _swingComponent.addContainerListener(this);
139 }
140
141 @Override
142 public AxisAlignedBoxBounds getContentBounds() {
143 //final Rectangle bounds = _swingComponent.getBounds();
144 //final AccessibleContext accessibleContext = _swingComponent.getAccessibleContext();
145 //if (accessibleContext != null) {
146 // final Rectangle accessibleBounds = _swingComponent.getAccessibleContext().getAccessibleComponent().getBounds();
147 // return new AxisAlignedBoxBounds(bounds.x, bounds.y, bounds.width, bounds.height + accessibleBounds.height);
148 //} else {
149 // return new AxisAlignedBoxBounds(bounds.x, bounds.y, bounds.width, bounds.height);
150 //}
151 final Rectangle bounds = _swingComponent.getBounds();
152 return new AxisAlignedBoxBounds(bounds.x, bounds.y, bounds.width, bounds.height);
153 }
154
155 @Override
156 protected void layout() {
157 layout(_swingComponent);
158 }
159
160 private void keyListenerToChildren(Component parent, boolean add) {
161 List<Component> components = new LinkedList<Component>();
162 components.add(parent);
163 while(!components.isEmpty()) {
164 Component c = components.remove(0);
165 if(c instanceof Container) {
166 components.addAll(Arrays.asList(((Container)c).getComponents()));
167 }
168 if(add && !Arrays.asList(c.getKeyListeners()).contains(this)) {
169 c.addKeyListener(this);
170 } else if (!add && Arrays.asList(c.getKeyListeners()).contains(this)) {
171 c.removeKeyListener(this);
172 }
173 }
174 }
175
176 @Override
177 protected void onMoved()
178 {
179 // Do nothing
180 }
181
182 @Override
183 protected void onSizeChanged()
184 {
185 onBoundsChanged();
186 layout(_swingComponent);
187 }
188
189 @Override
190 public final void onBoundsChanged()
191 {
192 if (_swingComponent == null) {
193 return;
194 }
195
196 if (isFixedSize()) {
197 _swingComponent.setBounds(getX(), getY(), getMaxWidth(), getMaxHeight());
198 } else {
199 _swingComponent.setBounds(getX(), getY(), getWidth(), getHeight());
200 }
201 }
202
203 private void prepareToPaint()
204 {
205 _isReadyToPaint = true;
206 layout(_swingComponent);
207 ignoreAWTPainting(_swingComponent);
208 }
209
210 private void ignoreAWTPainting(Component c)
211 {
212 if (c == null) {
213 return;
214 }
215
216 if (c instanceof JComponent) {
217 ((JComponent) c).setDoubleBuffered(false);
218 }
219 c.setIgnoreRepaint(true);
220
221 if (c instanceof Container) {
222 for (Component child : ((Container) c).getComponents()) {
223 if(child instanceof Container) {
224 ignoreAWTPainting(child);
225 } else {
226 if(child instanceof JComponent) {
227 ((JComponent) child).setDoubleBuffered(false);
228 }
229 child.setIgnoreRepaint(true);
230 }
231 }
232 }
233 }
234
235 /**
236 * Due to absolute positioning...
237 *
238 * @param parent
239 */
240 private void layout(Component parent)
241 {
242 if (parent == null) {
243 return;
244 }
245
246 parent.validate();
247
248 if (parent instanceof Container) {
249 for (Component child : ((Container) parent).getComponents()) {
250 layout(child);
251 }
252 }
253 }
254
255 @Override
256 protected final void paintWidget()
257 {
258 if (!_isReadyToPaint) {
259 prepareToPaint();
260 }
261
262 Graphics2D g = SwingMiscManager.getIfUsingSwingGraphicsManager().getCurrentSurface();
263
264 paintSwingWidget(g);
265 }
266
267 /** Can be overridden to enable custom painting of widgets. */
268 protected void paintSwingWidget(Graphics2D g)
269 {
270 final Point location = _swingComponent.getLocation();
271 int x = location.x;
272 int y = location.y;
273 g.translate(x, y);
274 _swingComponent.paint(g);
275 g.translate(-x, -y);
276 }
277
278 @Override
279 public boolean isSupportedOnEcosystem(Ecosystem type)
280 {
281 return type == Ecosystem.Swing;
282 }
283}
Note: See TracBrowser for help on using the repository browser.