[1098] | 1 | package org.expeditee.items.widgets;
|
---|
| 2 |
|
---|
| 3 | import java.awt.Component;
|
---|
| 4 | import java.awt.Container;
|
---|
| 5 | import java.awt.Graphics2D;
|
---|
[1143] | 6 | import java.awt.Point;
|
---|
[1177] | 7 | import java.awt.Rectangle;
|
---|
| 8 | import java.awt.event.ContainerEvent;
|
---|
| 9 | import java.awt.event.ContainerListener;
|
---|
| 10 | import java.awt.event.KeyEvent;
|
---|
| 11 | import java.awt.event.KeyListener;
|
---|
| 12 | import java.util.Arrays;
|
---|
| 13 | import java.util.LinkedList;
|
---|
| 14 | import java.util.List;
|
---|
[1098] | 15 |
|
---|
| 16 | import javax.swing.JComponent;
|
---|
| 17 |
|
---|
[1177] | 18 | import org.expeditee.core.bounds.AxisAlignedBoxBounds;
|
---|
| 19 | import org.expeditee.gio.EcosystemManager;
|
---|
[1098] | 20 | import org.expeditee.gio.EcosystemManager.Ecosystem;
|
---|
[1177] | 21 | import org.expeditee.gio.swing.SwingGraphicsManager;
|
---|
[1098] | 22 | import org.expeditee.gio.swing.SwingMiscManager;
|
---|
[1177] | 23 | import org.expeditee.gui.DisplayController;
|
---|
| 24 | import org.expeditee.items.ItemParentStateChangedEvent;
|
---|
[1098] | 25 | import org.expeditee.items.Text;
|
---|
[1177] | 26 | import org.expeditee.items.UserAppliedPermission;
|
---|
[1098] | 27 |
|
---|
[1177] | 28 | public abstract class SwingWidget extends Widget implements ContainerListener, KeyListener
|
---|
[1098] | 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;
|
---|
[1177] | 38 |
|
---|
[1098] | 39 | protected SwingWidget(Text source, JComponent component, int minWidth, int maxWidth, int minHeight, int maxHeight)
|
---|
| 40 | {
|
---|
| 41 | super(source, minWidth, maxWidth, minHeight, maxHeight);
|
---|
| 42 |
|
---|
[1177] | 43 | if (component == null) {
|
---|
| 44 | throw new NullPointerException("component");
|
---|
| 45 | }
|
---|
| 46 |
|
---|
[1098] | 47 | _swingComponent = component;
|
---|
[1177] | 48 | _swingComponent.setFocusable(true);
|
---|
| 49 | addKeyListenerToWidget();
|
---|
| 50 | addThisAsContainerListenerToContent();
|
---|
[1098] | 51 | onBoundsChanged();
|
---|
[1177] | 52 |
|
---|
[1511] | 53 | System.err.println("SwingWidget::Suppressed static setDefaultLightWeightPopupEnabled to false.");
|
---|
| 54 | //JPopupMenu.setDefaultLightWeightPopupEnabled(false);
|
---|
[1098] | 55 | }
|
---|
| 56 |
|
---|
| 57 | public JComponent getComponent()
|
---|
| 58 | {
|
---|
| 59 | return _swingComponent;
|
---|
| 60 | }
|
---|
| 61 |
|
---|
| 62 | @Override
|
---|
[1177] | 63 | public void keyTyped(KeyEvent e) {
|
---|
| 64 |
|
---|
| 65 | int keyCode = e.getKeyCode();
|
---|
| 66 |
|
---|
| 67 | if (keyCode >= KeyEvent.VK_F1 && keyCode <= KeyEvent.VK_F12) {
|
---|
[1191] | 68 | //((SwingInputManager) EcosystemManager.getInputManager()).keyTyped(e);
|
---|
[1177] | 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) {
|
---|
[1191] | 77 | //((SwingInputManager) EcosystemManager.getInputManager()).keyTyped(e);
|
---|
[1177] | 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) {
|
---|
[1191] | 86 | //((SwingInputManager) EcosystemManager.getInputManager()).keyTyped(e);
|
---|
[1177] | 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
|
---|
[1098] | 176 | protected void onMoved()
|
---|
| 177 | {
|
---|
| 178 | // Do nothing
|
---|
| 179 | }
|
---|
| 180 |
|
---|
| 181 | @Override
|
---|
| 182 | protected void onSizeChanged()
|
---|
| 183 | {
|
---|
| 184 | onBoundsChanged();
|
---|
| 185 | layout(_swingComponent);
|
---|
| 186 | }
|
---|
| 187 |
|
---|
[1177] | 188 | @Override
|
---|
[1098] | 189 | public final void onBoundsChanged()
|
---|
| 190 | {
|
---|
[1177] | 191 | if (_swingComponent == null) {
|
---|
| 192 | return;
|
---|
| 193 | }
|
---|
[1098] | 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 | {
|
---|
[1177] | 211 | if (c == null) {
|
---|
| 212 | return;
|
---|
| 213 | }
|
---|
[1098] | 214 |
|
---|
[1177] | 215 | if (c instanceof JComponent) {
|
---|
| 216 | ((JComponent) c).setDoubleBuffered(false);
|
---|
| 217 | }
|
---|
[1098] | 218 | c.setIgnoreRepaint(true);
|
---|
[1177] | 219 |
|
---|
[1098] | 220 | if (c instanceof Container) {
|
---|
| 221 | for (Component child : ((Container) c).getComponents()) {
|
---|
[1177] | 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 | }
|
---|
[1098] | 230 | }
|
---|
| 231 | }
|
---|
| 232 | }
|
---|
| 233 |
|
---|
| 234 | /**
|
---|
| 235 | * Due to absolute positioning...
|
---|
| 236 | *
|
---|
| 237 | * @param parent
|
---|
| 238 | */
|
---|
[1177] | 239 | private void layout(Component parent)
|
---|
[1098] | 240 | {
|
---|
[1177] | 241 | if (parent == null) {
|
---|
| 242 | return;
|
---|
| 243 | }
|
---|
[1098] | 244 |
|
---|
| 245 | parent.validate();
|
---|
| 246 |
|
---|
| 247 | if (parent instanceof Container) {
|
---|
| 248 | for (Component child : ((Container) parent).getComponents()) {
|
---|
| 249 | layout(child);
|
---|
| 250 | }
|
---|
[1177] | 251 | }
|
---|
[1098] | 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 | {
|
---|
[1152] | 269 | final Point location = _swingComponent.getLocation();
|
---|
| 270 | int x = location.x;
|
---|
| 271 | int y = location.y;
|
---|
| 272 | g.translate(x, y);
|
---|
[1098] | 273 | _swingComponent.paint(g);
|
---|
[1152] | 274 | g.translate(-x, -y);
|
---|
[1098] | 275 | }
|
---|
| 276 |
|
---|
| 277 | @Override
|
---|
| 278 | public boolean isSupportedOnEcosystem(Ecosystem type)
|
---|
| 279 | {
|
---|
| 280 | return type == Ecosystem.Swing;
|
---|
| 281 | }
|
---|
| 282 | }
|
---|