IDEA-57649 "locals" window can be minimized to horizontal size 0
[idea/community.git] / platform / platform-api / src / com / intellij / openapi / ui / ThreeComponentsSplitter.java
1 /*
2  * Copyright 2000-2015 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.openapi.ui;
17
18 import com.intellij.icons.AllIcons;
19 import com.intellij.openapi.Disposable;
20 import com.intellij.openapi.util.Disposer;
21 import com.intellij.openapi.util.Weighted;
22 import com.intellij.openapi.wm.IdeGlassPane;
23 import com.intellij.openapi.wm.IdeGlassPaneUtil;
24 import com.intellij.ui.ClickListener;
25 import com.intellij.ui.UIBundle;
26 import com.intellij.util.ui.JBUI;
27 import com.intellij.util.ui.update.Activatable;
28 import com.intellij.util.ui.update.UiNotifyConnector;
29 import org.jetbrains.annotations.NotNull;
30 import org.jetbrains.annotations.Nullable;
31
32 import javax.swing.*;
33 import java.awt.*;
34 import java.awt.event.MouseAdapter;
35 import java.awt.event.MouseEvent;
36
37 /**
38  * @author Vladimir Kondratyev
39  */
40 public class ThreeComponentsSplitter extends JPanel implements Disposable {
41   private int myDividerWidth;
42   /**
43    *                        /------/
44    *                        |  1   |
45    * This is vertical split |------|
46    *                        |  2   |
47    *                        /------/
48    *
49    *                          /-------/
50    *                          |   |   |
51    * This is horizontal split | 1 | 2 |
52    *                          |   |   |
53    *                          /-------/
54    */
55   private boolean myVerticalSplit;
56   private boolean myHonorMinimumSize = false;
57
58   private final Divider myFirstDivider;
59   private final Divider myLastDivider;
60
61   @Nullable private JComponent myFirstComponent;
62   @Nullable private JComponent myInnerComponent;
63   @Nullable private JComponent myLastComponent;
64
65   private int myFirstSize = 0;
66   private int myLastSize = 0;
67   private int myMinSize = 0;
68
69   private boolean myShowDividerControls;
70   private int myDividerZone;
71
72
73   /**
74    * Creates horizontal split with proportion equals to .5f
75    */
76   public ThreeComponentsSplitter() {
77     this(false);
78   }
79
80
81   public ThreeComponentsSplitter(boolean vertical) {
82     myVerticalSplit = vertical;
83     myShowDividerControls = false;
84     myFirstDivider = new Divider(true);
85     Disposer.register(this, myFirstDivider);
86     myLastDivider = new Divider(false);
87     Disposer.register(this, myLastDivider);
88
89     myDividerWidth = 7;
90     setOpaque(false);
91     add(myFirstDivider);
92     add(myLastDivider);
93   }
94
95   public void setShowDividerControls(boolean showDividerControls) {
96     myShowDividerControls = showDividerControls;
97     setOrientation(myVerticalSplit);
98   }
99
100   public void setDividerMouseZoneSize(int size) {
101     myDividerZone = size;
102   }
103
104   public boolean isHonorMinimumSize() {
105     return myHonorMinimumSize;
106   }
107
108   public void setHonorComponentsMinimumSize(boolean honorMinimumSize) {
109     myHonorMinimumSize = honorMinimumSize;
110   }
111
112   public boolean isVisible() {
113     return super.isVisible() && (firstVisible() || innerVisible() || lastVisible());
114   }
115
116   private boolean lastVisible() {
117     return !Splitter.isNull(myLastComponent) && myLastComponent.isVisible();
118   }
119
120   private boolean innerVisible() {
121     return !Splitter.isNull(myInnerComponent) && myInnerComponent.isVisible();
122   }
123
124   private boolean firstVisible() {
125     return !Splitter.isNull(myFirstComponent) && myFirstComponent.isVisible();
126   }
127
128   private int visibleDividersCount() {
129     int count = 0;
130     if (firstDividerVisible()) count++;
131     if (lastDividerVisible()) count++;
132     return count;
133   }
134
135   private boolean firstDividerVisible() {
136     return firstVisible() && innerVisible() || firstVisible() && lastVisible() && !innerVisible();
137   }
138
139   private boolean lastDividerVisible() {
140     return innerVisible() && lastVisible();
141   }
142
143   public Dimension getMinimumSize() {
144     if (isHonorMinimumSize()) {
145       final int dividerWidth = getDividerWidth();
146       final Dimension firstSize = myFirstComponent != null ? myFirstComponent.getMinimumSize() : JBUI.emptySize();
147       final Dimension lastSize = myLastComponent != null ? myLastComponent.getMinimumSize() : JBUI.emptySize();
148       final Dimension innerSize = myInnerComponent != null ? myInnerComponent.getMinimumSize() : JBUI.emptySize();
149       if (getOrientation()) {
150         int width = Math.max(firstSize.width, Math.max(lastSize.width, innerSize.width));
151         int height = visibleDividersCount() * dividerWidth;
152         height += firstSize.height;
153         height += lastSize.height;
154         height += innerSize.height;
155         return new Dimension(width, height);
156       }
157       else {
158         int heigth = Math.max(firstSize.height, Math.max(lastSize.height, innerSize.height));
159         int width = visibleDividersCount() * dividerWidth;
160         width += firstSize.width;
161         width += lastSize.width;
162         width += innerSize.width;
163         return new Dimension(width, heigth);
164       }
165     }
166     return super.getMinimumSize();
167   }
168
169   public void doLayout() {
170     final int width = getWidth();
171     final int height = getHeight();
172
173     Rectangle firstRect = new Rectangle();
174     Rectangle firstDividerRect = new Rectangle();
175     Rectangle lastDividerRect = new Rectangle();
176     Rectangle lastRect = new Rectangle();
177     Rectangle innerRect = new Rectangle();
178     final int componentSize = getOrientation() ? height : width;
179     int dividerWidth = getDividerWidth();
180     int dividersCount = visibleDividersCount();
181
182     int firstCompontSize;
183     int lastComponentSize;
184     int innerComponentSize;
185     if(componentSize <= dividersCount * dividerWidth) {
186       firstCompontSize = 0;
187       lastComponentSize = 0;
188       innerComponentSize = 0;
189       dividerWidth = componentSize;
190     }
191     else {
192       firstCompontSize = getFirstSize();
193       lastComponentSize = getLastSize();
194       int sizeLack = firstCompontSize + lastComponentSize - (componentSize - dividersCount * dividerWidth - myMinSize);
195       if (sizeLack > 0) {
196         // Lacking size. Reduce first & last component's size, inner -> MIN_SIZE
197         double firstSizeRatio = (double)firstCompontSize / (firstCompontSize + lastComponentSize);
198         if (firstCompontSize > 0) {
199           firstCompontSize -= sizeLack * firstSizeRatio;
200           firstCompontSize = Math.max(myMinSize, firstCompontSize);
201         }
202         if (lastComponentSize > 0) {
203           lastComponentSize -= sizeLack * (1 - firstSizeRatio);
204           lastComponentSize = Math.max(myMinSize, lastComponentSize);
205         }
206         innerComponentSize = getMinSize(myInnerComponent);
207       }
208       else {
209         innerComponentSize = Math.max(getMinSize(myInnerComponent), componentSize - dividersCount * dividerWidth - getFirstSize() - getLastSize());
210       }
211
212       if (!innerVisible()) {
213         lastComponentSize += innerComponentSize;
214         innerComponentSize = 0;
215         if (!lastVisible()) {
216           firstCompontSize = componentSize;
217         }
218       }
219     }
220
221     if (getOrientation()) {
222       int space = firstCompontSize;
223       firstRect.setBounds(0, 0, width, firstCompontSize);
224       if (firstDividerVisible()) {
225         firstDividerRect.setBounds(0, space, width, dividerWidth);
226         space += dividerWidth;
227       }
228
229       innerRect.setBounds(0, space, width, innerComponentSize);
230       space += innerComponentSize;
231
232       if (lastDividerVisible()) {
233         lastDividerRect.setBounds(0, space, width, dividerWidth);
234         space += dividerWidth;
235       }
236
237       lastRect.setBounds(0, space, width, lastComponentSize);
238     }
239     else {
240       int space = firstCompontSize;
241       firstRect.setBounds(0, 0, firstCompontSize, height);
242
243       if (firstDividerVisible()) {
244         firstDividerRect.setBounds(space, 0, dividerWidth, height);
245         space += dividerWidth;
246       }
247
248       innerRect.setBounds(space, 0, innerComponentSize, height);
249       space += innerComponentSize;
250
251       if (lastDividerVisible()) {
252         lastDividerRect.setBounds(space, 0, dividerWidth, height);
253         space += dividerWidth;
254       }
255
256       lastRect.setBounds(space, 0, lastComponentSize, height);
257     }
258
259     myFirstDivider.setVisible(firstDividerVisible());
260     myFirstDivider.setBounds(firstDividerRect);
261     myFirstDivider.doLayout();
262
263     myLastDivider.setVisible(lastDividerVisible());
264     myLastDivider.setBounds(lastDividerRect);
265     myLastDivider.doLayout();
266
267     validateIfNeeded(myFirstComponent, firstRect);
268     validateIfNeeded(myInnerComponent, innerRect);
269     validateIfNeeded(myLastComponent, lastRect);
270   }
271
272   private static void validateIfNeeded(final JComponent c, final Rectangle rect) {
273     if (!Splitter.isNull(c)) {
274       if (!c.getBounds().equals(rect)) {
275         c.setBounds(rect);
276         c.revalidate();
277       }
278     } else {
279       Splitter.hideNull(c);
280     }
281   }
282
283
284   public int getDividerWidth() {
285     return myDividerWidth;
286   }
287
288   public void setDividerWidth(int width) {
289     if (width < 0) {
290       throw new IllegalArgumentException("Wrong divider width: " + width);
291     }
292     if (myDividerWidth != width) {
293       myDividerWidth = width;
294       doLayout();
295       repaint();
296     }
297   }
298
299   /**
300    * @return <code>true</code> if splitter has vertical orientation, <code>false</code> otherwise
301    */
302   public boolean getOrientation() {
303     return myVerticalSplit;
304   }
305
306   /**
307    * @param verticalSplit <code>true</code> means that splitter will have vertical split
308    */
309   public void setOrientation(boolean verticalSplit) {
310     myVerticalSplit = verticalSplit;
311     myFirstDivider.setOrientation(verticalSplit);
312     myLastDivider.setOrientation(verticalSplit);
313     doLayout();
314     repaint();
315   }
316
317   @Nullable
318   public JComponent getFirstComponent() {
319     return myFirstComponent;
320   }
321
322   /**
323    * Sets component which is located as the "first" splitted area. The method doesn't validate and
324    * repaint the splitter. If there is already
325    *
326    */
327   public void setFirstComponent(@Nullable JComponent component) {
328     if (myFirstComponent != component) {
329       if (myFirstComponent != null) {
330         remove(myFirstComponent);
331       }
332       myFirstComponent = component;
333       if (myFirstComponent != null) {
334         add(myFirstComponent);
335         myFirstComponent.invalidate();
336       }
337     }
338   }
339
340   @Nullable
341   public JComponent getLastComponent() {
342     return myLastComponent;
343   }
344
345
346   /**
347    * Sets component which is located as the "secont" splitted area. The method doesn't validate and
348    * repaint the splitter.
349    *
350    */
351   public void setLastComponent(@Nullable JComponent component) {
352     if (myLastComponent != component) {
353       if (myLastComponent != null) {
354         remove(myLastComponent);
355       }
356       myLastComponent = component;
357       if (myLastComponent != null) {
358         add(myLastComponent);
359         myLastComponent.invalidate();
360       }
361     }
362   }
363
364   @Nullable
365   public JComponent getInnerComponent() {
366     return myInnerComponent;
367   }
368
369
370   /**
371    * Sets component which is located as the "inner" splitted area. The method doesn't validate and
372    * repaint the splitter.
373    *
374    */
375   public void setInnerComponent(@Nullable JComponent component) {
376     if (myInnerComponent != component) {
377       if (myInnerComponent != null) {
378         remove(myInnerComponent);
379       }
380       myInnerComponent = component;
381       if (myInnerComponent != null) {
382         add(myInnerComponent);
383         myInnerComponent.invalidate();
384       }
385     }
386   }
387   public void setMinSize(int minSize) {
388     myMinSize = Math.max(0, minSize);
389     doLayout();
390     repaint();
391   }
392
393
394   public void setFirstSize(final int size) {
395     myFirstSize = size;
396     doLayout();
397     repaint();
398   }
399
400   public void setLastSize(final int size) {
401     myLastSize = size;
402     doLayout();
403     repaint();
404   }
405
406   public int getFirstSize() {
407     return firstVisible() ? myFirstSize : 0;
408   }
409
410   public int getLastSize() {
411     return lastVisible() ? myLastSize : 0;
412   }
413
414   public int getMinSize(boolean first) {
415     return getMinSize(first? myFirstComponent : myLastComponent);
416   }
417
418   public int getMaxSize(boolean first) {
419     final int size = getOrientation() ? this.getHeight() : this.getWidth();
420     return size - (first? myLastSize: myFirstSize) - myMinSize;
421   }
422
423   private int getMinSize(JComponent component) {
424     if (isHonorMinimumSize()) {
425       if (component != null && myFirstComponent != null && myFirstComponent.isVisible() && myLastComponent != null && myLastComponent.isVisible()) {
426         if (getOrientation()) {
427           return component.getMinimumSize().height;
428         }
429         else {
430           return component.getMinimumSize().width;
431         }
432       }
433     }
434     return myMinSize;
435   }
436
437   @Override
438   public void dispose() {
439     myLastComponent = null;
440     myFirstComponent = null;
441     myInnerComponent = null;
442     removeAll();
443     Container container = getParent();
444     if (container != null) {
445       container.remove(this);
446     }
447   }
448
449   private class Divider extends JPanel implements Disposable {
450     protected boolean myDragging;
451     protected Point myPoint;
452     private final boolean myIsFirst;
453
454     private IdeGlassPane myGlassPane;
455
456     private class MyMouseAdapter extends MouseAdapter implements Weighted {
457       @Override
458       public void mousePressed(MouseEvent e) {
459         _processMouseEvent(e);
460       }
461
462       @Override
463       public void mouseReleased(MouseEvent e) {
464         _processMouseEvent(e);
465       }
466
467       @Override
468       public void mouseMoved(MouseEvent e) {
469         _processMouseMotionEvent(e);
470       }
471
472       @Override
473       public void mouseDragged(MouseEvent e) {
474         _processMouseMotionEvent(e);
475       }
476       @Override
477       public double getWeight() {
478         return 1;
479       }
480       private void _processMouseMotionEvent(MouseEvent e) {
481         MouseEvent event = getTargetEvent(e);
482         if (event == null) {
483           myGlassPane.setCursor(null, myListener);
484           return;
485         }
486
487         processMouseMotionEvent(event);
488         if (event.isConsumed()) {
489           e.consume();
490         }
491       }
492
493       private void _processMouseEvent(MouseEvent e) {
494         MouseEvent event = getTargetEvent(e);
495         if (event == null) {
496           myGlassPane.setCursor(null, myListener);
497           return;
498         }
499
500         processMouseEvent(event);
501         if (event.isConsumed()) {
502           e.consume();
503         }
504       }
505     }
506
507     private final MouseAdapter myListener = new MyMouseAdapter();
508
509
510     private MouseEvent getTargetEvent(MouseEvent e) {
511       return SwingUtilities.convertMouseEvent(e.getComponent(), e, this);
512     }
513
514     private boolean myWasPressedOnMe;
515
516     public Divider(boolean isFirst) {
517       super(new GridBagLayout());
518       setFocusable(false);
519       enableEvents(MouseEvent.MOUSE_EVENT_MASK | MouseEvent.MOUSE_MOTION_EVENT_MASK);
520       myIsFirst = isFirst;
521       setOrientation(myVerticalSplit);
522
523       new UiNotifyConnector.Once(this, new Activatable.Adapter() {
524         @Override
525         public void showNotify() {
526           init();
527         }
528       });
529     }
530
531     private boolean isInside(Point p) {
532       if (!isVisible()) return false;
533
534       if (myVerticalSplit) {
535         if (p.x >= 0 && p.x < getWidth()) {
536           if (getHeight() > 0) {
537             return p.y >= 0 && p.y < getHeight();
538           }
539           else {
540             return p.y >= -myDividerZone / 2 && p.y <= myDividerZone / 2;
541           }
542         }
543       }
544       else {
545         if (p.y >= 0 && p.y < getHeight()) {
546           if (getWidth() > 0) {
547             return p.x >= 0 && p.x < getWidth();
548           }
549           else {
550             return p.x >= -myDividerZone / 2 && p.x <= myDividerZone / 2;
551           }
552         }
553       }
554
555       return false;
556     }
557
558     private void init() {
559       myGlassPane = IdeGlassPaneUtil.find(this);
560       myGlassPane.addMouseMotionPreprocessor(myListener, this);
561       myGlassPane.addMousePreprocessor(myListener, this);
562     }
563
564     public void dispose() {
565     }
566
567     private void setOrientation(boolean isVerticalSplit) {
568       removeAll();
569
570       if (!myShowDividerControls) {
571         return;
572       }
573
574       int xMask = isVerticalSplit ? 1 : 0;
575       int yMask = isVerticalSplit ? 0 : 1;
576
577       Icon glueIcon = isVerticalSplit ? AllIcons.General.SplitGlueV : AllIcons.General.SplitCenterH;
578       int glueFill = isVerticalSplit ? GridBagConstraints.VERTICAL : GridBagConstraints.HORIZONTAL;
579       add(new JLabel(glueIcon),
580           new GridBagConstraints(0, 0, 1, 1, 0, 0, isVerticalSplit ? GridBagConstraints.EAST : GridBagConstraints.NORTH, glueFill, new Insets(0, 0, 0, 0), 0, 0));
581       JLabel splitDownlabel = new JLabel(isVerticalSplit ? AllIcons.General.SplitDown : AllIcons.General.SplitRight);
582       splitDownlabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
583       splitDownlabel.setToolTipText(isVerticalSplit ? UIBundle.message("splitter.down.tooltip.text") : UIBundle
584         .message("splitter.right.tooltip.text"));
585       new ClickListener() {
586         @Override
587         public boolean onClick(@NotNull MouseEvent e, int clickCount) {
588           if (myInnerComponent != null) {
589             final int income = myVerticalSplit ? myInnerComponent.getHeight() : myInnerComponent.getWidth();
590             if (myIsFirst) {
591               setFirstSize(myFirstSize + income);
592             }
593             else {
594               setLastSize(myLastSize + income);
595             }
596           }
597           return true;
598         }
599       }.installOn(splitDownlabel);
600
601       add(splitDownlabel,
602           new GridBagConstraints(isVerticalSplit ? 1 : 0,
603                                  isVerticalSplit ? 0 : 5,
604                                  1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
605       //
606       add(new JLabel(glueIcon),
607           new GridBagConstraints(2 * xMask, 2 * yMask, 1, 1, 0, 0, GridBagConstraints.CENTER, glueFill, new Insets(0, 0, 0, 0), 0, 0));
608       JLabel splitCenterlabel = new JLabel(isVerticalSplit ? AllIcons.General.SplitCenterV : AllIcons.General.SplitCenterH);
609       splitCenterlabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
610       splitCenterlabel.setToolTipText(UIBundle.message("splitter.center.tooltip.text"));
611       new ClickListener() {
612         @Override
613         public boolean onClick(@NotNull MouseEvent e, int clickCount) {
614           center();
615           return true;
616         }
617       }.installOn(splitCenterlabel);
618       add(splitCenterlabel,
619           new GridBagConstraints(3 * xMask, 3 * yMask, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
620       add(new JLabel(glueIcon),
621           new GridBagConstraints(4 * xMask, 4 * yMask, 1, 1, 0, 0, GridBagConstraints.CENTER, glueFill, new Insets(0, 0, 0, 0), 0, 0));
622       //
623       JLabel splitUpLabel = new JLabel(isVerticalSplit ? AllIcons.General.SplitUp : AllIcons.General.SplitLeft);
624       splitUpLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
625       splitUpLabel.setToolTipText(isVerticalSplit ? UIBundle.message("splitter.up.tooltip.text") : UIBundle
626         .message("splitter.left.tooltip.text"));
627       new ClickListener() {
628         @Override
629         public boolean onClick(@NotNull MouseEvent e, int clickCount) {
630           if (myInnerComponent != null) {
631             final int income = myVerticalSplit ? myInnerComponent.getHeight() : myInnerComponent.getWidth();
632             if (myIsFirst) {
633               setFirstSize(myFirstSize + income);
634             }
635             else {
636               setLastSize(myLastSize + income);
637             }
638           }
639           return true;
640         }
641       }.installOn(splitUpLabel);
642
643       add(splitUpLabel,
644           new GridBagConstraints(isVerticalSplit ? 5 : 0,
645                                  isVerticalSplit ? 0 : 1,
646                                  1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
647       add(new JLabel(glueIcon),
648           new GridBagConstraints(6 * xMask, 6 * yMask, 1, 1, 0, 0,
649                                  isVerticalSplit ? GridBagConstraints.WEST : GridBagConstraints.SOUTH, glueFill, new Insets(0, 0, 0, 0), 0, 0));
650     }
651
652     private void center() {
653       if (myInnerComponent != null) {
654         final int total = myFirstSize + (myVerticalSplit ? myInnerComponent.getHeight() : myInnerComponent.getWidth());
655         if (myIsFirst) {
656           setFirstSize(total / 2);
657         }
658         else {
659           setLastSize(total / 2);
660         }
661       }
662     }
663
664     protected void processMouseMotionEvent(MouseEvent e) {
665       super.processMouseMotionEvent(e);
666
667       if (!isShowing()) return;
668
669       if (MouseEvent.MOUSE_DRAGGED == e.getID() && myWasPressedOnMe) {
670         myDragging = true;
671         setCursor(getResizeCursor());
672         myGlassPane.setCursor(getResizeCursor(), myListener);
673
674         myPoint = SwingUtilities.convertPoint(this, e.getPoint(), ThreeComponentsSplitter.this);
675         final int size = getOrientation() ? ThreeComponentsSplitter.this.getHeight() : ThreeComponentsSplitter.this.getWidth();
676         if (getOrientation()) {
677           if (size > 0 || myDividerZone > 0) {
678             if (myIsFirst) {
679               setFirstSize(Math.min(size - myLastSize - getMinSize(myInnerComponent) - getDividerWidth() * visibleDividersCount(), Math.max(getMinSize(myFirstComponent), myPoint.y)));
680             }
681             else {
682               setLastSize(Math.min(size - myFirstSize - getMinSize(myInnerComponent) - getDividerWidth() * visibleDividersCount(), Math.max(getMinSize(myLastComponent), size - myPoint.y - getDividerWidth())));
683             }
684           }
685         }
686         else {
687           if (size > 0 || myDividerZone > 0) {
688             if (myIsFirst) {
689               setFirstSize(Math.min(size - myLastSize - getMinSize(myInnerComponent) - getDividerWidth() * visibleDividersCount(), Math.max(getMinSize(myFirstComponent), myPoint.x)));
690             }
691             else {
692               setLastSize(Math.min(size - myFirstSize - getMinSize(myInnerComponent) - getDividerWidth() * visibleDividersCount(), Math.max(getMinSize(myLastComponent), size - myPoint.x - getDividerWidth())));
693             }
694           }
695         }
696         ThreeComponentsSplitter.this.doLayout();
697       } else if (MouseEvent.MOUSE_MOVED == e.getID()) {
698         if (myGlassPane != null) {
699           if (isInside(e.getPoint())) {
700             myGlassPane.setCursor(getResizeCursor(), myListener);
701             e.consume();
702           } else {
703             myGlassPane.setCursor(null, myListener);
704           }
705         }
706       }
707
708       if (myWasPressedOnMe) {
709         e.consume();
710       }
711     }
712
713     protected void processMouseEvent(MouseEvent e) {
714       super.processMouseEvent(e);
715       if (!isShowing()) {
716         return;
717       }
718       switch (e.getID()) {
719         case MouseEvent.MOUSE_ENTERED:
720           setCursor(getResizeCursor());
721           break;
722         case MouseEvent.MOUSE_EXITED:
723           if (!myDragging) {
724             setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
725           }
726           break;
727         case MouseEvent.MOUSE_PRESSED:
728           if (isInside(e.getPoint())) {
729             myWasPressedOnMe = true;
730             myGlassPane.setCursor(getResizeCursor(), myListener);
731             e.consume();
732           } else {
733             myWasPressedOnMe = false;
734           }
735           break;
736         case MouseEvent.MOUSE_RELEASED:
737           if (myWasPressedOnMe) {
738             e.consume();
739           }
740           if (isInside(e.getPoint())) {
741             myGlassPane.setCursor(getResizeCursor(), myListener);
742           }
743           myWasPressedOnMe = false;
744           myDragging = false;
745           myPoint = null;
746           break;
747         case MouseEvent.MOUSE_CLICKED:
748           if (e.getClickCount() == 2) {
749             center();
750           }
751           break;
752       }
753     }
754   }
755
756   private Cursor getResizeCursor() {
757     return getOrientation() ? Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR) : Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR);
758   }
759 }