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

Last change on this file since 1511 was 1511, checked in by bnemhaus, 4 years ago

Frame::Parse has been updated to include a new boolean parameter. When true, widgets that are created as a result of the parse send not only notify the widget framework that they have been added, but are also visible. When false, they only notify they have been added.

The widget framework now distinguishes between added and visible widgets, this fixes a bug. Bug: when programmatically adding a widget to not the current frame, it never gets properly removed and therefore still catches click events from users. By distinguishing between adding and making visible this is avoided.


Another bug has been fixed. Bug: When setting a text item to have a right anchor, and then subsequently reducing the size of the window, this text item would get a width of zero assigned. This was caused by some issues with the logic of how right margins for items were calculated.

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