Ignore:
Timestamp:
05/10/18 16:04:51 (6 years ago)
Author:
davidb
Message:

Reworking of the code-base to separate logic from graphics. This version of Expeditee now supports a JFX graphics as an alternative to SWING

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/expeditee/gui/Popup.java

    r919 r1102  
    1919package org.expeditee.gui;
    2020
    21 import java.awt.BasicStroke;
    22 import java.awt.Color;
    23 import java.awt.Component;
    24 import java.awt.Container;
    25 import java.awt.Graphics;
    26 import java.awt.Graphics2D;
    27 import java.awt.LayoutManager;
    28 
    29 import javax.swing.JComponent;
    30 import javax.swing.JPanel;
    31 
     21import org.expeditee.core.Clip;
     22import org.expeditee.core.Colour;
     23import org.expeditee.core.EnforcedClipStack.EnforcedClipKey;
     24import org.expeditee.core.Fill;
     25import org.expeditee.core.Lifetime;
     26import org.expeditee.core.Stroke;
     27import org.expeditee.core.bounds.AxisAlignedBoxBounds;
     28import org.expeditee.gio.EcosystemManager;
     29import org.expeditee.gio.GraphicsManager;
     30import org.expeditee.gui.PopupManager.PopupAnimator;
    3231import org.expeditee.items.ItemUtils;
    3332
    3433/**
     34 * A Custom swing pop-up in Expeditee.
    3535 *
    36  * A Custom swing popup in Expeditee.
    37  *
    38  * Expeditee popus can be re-used. Popups are always heavyweight (i.e. uses invalidation).
     36 * Expeditee pop-ups can be re-used. Pop-ups are always heavyweight (i.e. uses invalidation).
    3937 *
    4038 * @see {@link PopupManager}
    4139 *
    4240 * @author Brook Novak
    43  *
    4441 */
    45 public abstract class Popup extends JPanel {
    46        
     42public abstract class Popup
     43{
    4744        //Mike says: Can we get the border for the IW to which this popup corresponds?
    48         // Brook says: Would be nice - but popups are actually independant from widgets
     45        // Brook says: Would be nice - but popups are actually independent from widgets
    4946        //   =>Now: It is up to the user of the popup to set the border thickness
    50         private static final BasicStroke DEFAULT_STROKE = new BasicStroke(2.0f);
    51        
    52         private BasicStroke _borderStroke = DEFAULT_STROKE;
    53         private Color _borderColor = Color.BLACK;
    54        
    55         private boolean _isReadyToPaint = false;
     47        private static final Stroke DEFAULT_STROKE = new Stroke(2.0f);
     48       
     49        private Stroke _borderStroke = DEFAULT_STROKE;
     50        private Colour _borderColour = Colour.BLACK;
     51        private Fill _backgroundFill = new Fill(Colour.WHITE);
     52       
     53        private PopupAnimator _animator = null;
     54       
     55        private Lifetime _autoHideTime = new Lifetime(Lifetime.INFINITE_LIFETIME);
     56        private Runnable _autoHideRoutine = new Runnable()
     57        {
     58                @Override
     59                public void run()
     60                {
     61                        hide();
     62                        DisplayController.invalidateArea(getBounds());
     63                        DisplayController.requestRefresh(true);
     64                }
     65        };
     66       
     67        private boolean _hidden = true;
     68
    5669        private boolean _consumeBackClick = false;
    57         private boolean _autoHide = true;
    58 
    59         /**
    60          * Creates a new popup.
    61          * Autohide is set to true.
    62          *
    63          */
    64         public Popup() {
    65                 super();
    66                 setVisible(false);
    67         }
    68        
    69         /**
    70          * Creates a new popup.
    71          *
    72          * @param layout the LayoutManager to use
    73          */
    74         public Popup(LayoutManager layout) {
    75                 super(layout);
    76                 setVisible(false);
    77         }
    78 
    79         @Override
    80         public void paint(Graphics g) {
    81                 super.paint(g);
    82                
    83                 // Draw border - if not transparent
    84                 if (_borderStroke != null && _borderColor != null) {
    85                         g.setColor(_borderColor);
    86                         ((Graphics2D)g).setStroke(_borderStroke);
    87                         g.drawRect(0, 0, getWidth(), getHeight());
    88                 }
    89         }
    90        
    91         private void ignoreAWTPainting(Component c) {
    92                
    93                 if (c instanceof JComponent) {
    94                         ((JComponent)c).setDoubleBuffered(false);
    95                 }
    96                
    97                 c.setIgnoreRepaint(true);
    98                
    99                 if (c instanceof Container) {
    100                         for (Component child : ((Container) c).getComponents()) {
    101 
    102                                 if (child instanceof Container) {
    103                                         ignoreAWTPainting(child);
    104                                 } else {
    105                                         if (child instanceof JComponent) {
    106                                                 ((JComponent)child).setDoubleBuffered(false);
    107                                         }
    108                                        
    109                                         child.setIgnoreRepaint(true);
     70
     71        /**
     72         * Creates a new pop-up.
     73         * Auto-hide is set to true.
     74         */
     75        public Popup(PopupAnimator animator)
     76        {
     77                setAnimator(animator);
     78        }
     79       
     80        public Popup(PopupAnimator animator, long lifetime)
     81        {
     82                this(animator);
     83                _autoHideTime.setLifetime(lifetime);
     84        }
     85       
     86        public Lifetime getAutoHideTime()
     87        {
     88                return _autoHideTime;
     89        }
     90       
     91        public void setAnimator(PopupAnimator animator)
     92        {
     93                _animator = animator;
     94        }
     95       
     96        public PopupAnimator getAnimator()
     97        {
     98                return _animator;
     99        }
     100       
     101        public boolean isShowing()
     102        {
     103                return !_hidden;
     104        }
     105       
     106        public void show()
     107        {
     108                if (_hidden) onShow();
     109               
     110                if (_animator != null) {
     111                        _animator.show();
     112                        if (!_animator.isFinished()) {
     113                                _autoHideTime.cancelExpiry();
     114                        } else {
     115                                _autoHideTime.refresh();
     116                                _autoHideTime.onExpiry(_autoHideRoutine);
     117                        }
     118                } else {
     119                        _autoHideTime.refresh();
     120                        _autoHideTime.onExpiry(_autoHideRoutine);
     121                }
     122               
     123                _hidden = false;
     124        }
     125
     126        public void hide()
     127        {
     128                if (!_hidden) onHide();
     129               
     130                if (_animator != null) _animator.hide();
     131                _autoHideTime.cancelExpiry();
     132                _hidden = true;
     133        }
     134       
     135        public boolean update()
     136        {
     137                if (_animator != null) {
     138                        if (!_hidden && !_animator.isFinished()) {
     139                                if (!_animator.update()) {
     140                                        _autoHideTime.refresh();
     141                                        _autoHideTime.onExpiry(_autoHideRoutine);
    110142                                }
    111143                        }
    112                 }
    113                
    114         }
    115        
    116         /**
    117          * Ensures that AWT painting turned off
    118          */
    119         void prepareToPaint() {
    120                 if (!_isReadyToPaint) {
    121                         _isReadyToPaint = true;
    122                         ignoreAWTPainting(this);
    123                 }
    124         }
    125        
    126         /**
    127          * Invoked when the popup becomes hidden, or when the popup is animating to show but cancelled.
    128          */
    129         public void onHide() {}
    130        
    131         /**
    132          * Invoked when the popup shows. Note this might not eventuate for animated popups.
    133          */
    134         public void onShow() {}
    135        
    136         /**
    137          * Invoked when popups is going to show.
    138          * This always is invoked first.
    139          */
    140         public void onShowing() {}
    141 
    142         public boolean shouldConsumeBackClick() {
     144                       
     145                        if (_hidden && !_animator.isFinished()) {
     146                                return _animator.update();
     147                        }
     148                } else {
     149                        if (_autoHideTime.hasExpired()) hide();
     150                }
     151               
     152                return false;
     153               
     154        }
     155       
     156        public final void paint()
     157        {
     158                GraphicsManager g = EcosystemManager.getGraphicsManager();
     159               
     160                // Make sure the popup isn't hidden
     161                AxisAlignedBoxBounds currentBounds = getBounds();
     162                if (currentBounds == null) return;
     163               
     164                // Draw border and background
     165                g.drawRectangle(currentBounds, 0.0, _backgroundFill, _borderColour, _borderStroke, null);
     166               
     167                EnforcedClipKey key = g.pushClip(new Clip(currentBounds));
     168               
     169                paintInternal();
     170               
     171                g.popClip(key);
     172        }
     173       
     174        /** Draws the interior paint area of the popup. */
     175        protected abstract void paintInternal();
     176       
     177        /** Gets the bounds of this popup when it's fully shown. */
     178        public abstract AxisAlignedBoxBounds getFullBounds();
     179       
     180        /** Gets the bounds of this popup in its current animated state. */
     181        public AxisAlignedBoxBounds getBounds()
     182        {
     183                if (_animator == null) {
     184                        if (_autoHideTime.hasExpired()) {
     185                                return null;
     186                        } else {
     187                                return getFullBounds();
     188                        }
     189                }
     190               
     191                return _animator.getAnimatedBounds(getFullBounds());
     192        }
     193       
     194        /** Invoked when the popup becomes hidden, or when the popup is animating to show but cancelled. */
     195        public abstract void onHide();
     196       
     197        /** Invoked when the popup shows. Note this might not eventuate for animated popups. */
     198        public abstract void onShow();
     199
     200        public boolean shouldConsumeBackClick()
     201        {
    143202                return _consumeBackClick;
    144203        }
     
    150209         *              consume the back-click event.
    151210         */
    152         protected void setConsumeBackClick(boolean consumeBackClick) {
     211        protected void setConsumeBackClick(boolean consumeBackClick)
     212        {
    153213                _consumeBackClick = consumeBackClick;
    154         }
    155        
    156         /**
    157          * @param autoHideOn
    158          *              Set to True if this popup should auto hide. (The default).
    159          *              Set to false if this popup should be manually hidden.
    160          */
    161         protected void setAudoHide(boolean autoHideOn) {
    162                 _autoHide = autoHideOn;
    163214        }
    164215       
     
    167218         *              True if this popup auto hides.
    168219         */
    169         public boolean doesAutoHide() {
    170                 return _autoHide;
     220        public boolean doesAutoHide()
     221        {
     222                return _autoHideTime.remainingLifetime() != Lifetime.INFINITE_LIFETIME;
    171223        }
    172224       
     
    177229         *              The new thickness to set. Null for no border.
    178230         */
    179         public void setBorderThickness(float thickness) {
     231        public void setBorderThickness(float thickness)
     232        {
    180233                assert(thickness >= 0);
    181234               
    182                 if (_borderStroke != null && _borderStroke.getLineWidth() == thickness)
    183                         return;
     235                if (_borderStroke != null && _borderStroke.thickness == thickness) return;
    184236               
    185237                boolean posInvalidate = true;
    186238               
    187                 if (thickness < _borderStroke.getLineWidth()) {
     239                if (thickness < _borderStroke.thickness) {
    188240                        invalidateAppearance();
    189241                        posInvalidate = false;
    190242                }
    191243               
    192                 if (thickness == 0) _borderStroke = null;
    193                 else _borderStroke = new BasicStroke(thickness);
     244                if (thickness == 0) {
     245                        _borderStroke = null;
     246                } else {
     247                        _borderStroke = new Stroke(thickness);
     248                }
    194249               
    195250                if (posInvalidate) invalidateAppearance();
     
    201256         *              The border thickness of this popup. Zero or more.
    202257         */
    203         public float getBorderThickness() {
     258        public float getBorderThickness()
     259        {
    204260                if (_borderStroke == null) return 0.0f;
    205                 return _borderStroke.getLineWidth();
    206 
     261
     262                return _borderStroke.thickness;
    207263        }
    208264       
     
    214270         *              The new color. Null for transparent.
    215271         */
    216         public void setBorderColor(Color c) {
    217                
    218                 if (c == null && _borderColor != null)
     272        public void setBorderColor(Colour c)
     273        {
     274                if (c == null && _borderColour != null)  invalidateAppearance();
     275               
     276                if (c != _borderColour) {
     277                        _borderColour = c;
    219278                        invalidateAppearance();
    220                
    221                 if (c != _borderColor) {
    222                         _borderColor = c;
    223                         invalidateAppearance();
    224                 }
    225         }
    226        
    227         /**
    228          *
     279                }
     280        }
     281       
     282        /**
    229283         * @return
    230284         *              The border color for the popup. NUll if transparent
    231285         */
    232         public Color getBorderColor() {
    233                 return _borderColor;
    234         }
    235        
    236         /**
    237          * Invalidates the whole popup so that it must be fully repainted.
    238          */
    239         public void invalidateAppearance() {
    240                
    241                 if (_borderColor != null && _borderStroke != null && _borderStroke.getLineWidth() > 0) { // border
    242                         FrameGraphics.invalidateArea(ItemUtils.expandRectangle(getBounds(),
    243                                         (int)Math.ceil(getBorderThickness()) + 1));
     286        public Colour getBorderColor()
     287        {
     288                return _borderColour;
     289        }
     290       
     291        /**
     292         * Invalidates the whole pop-up so that it must be fully repainted.
     293         */
     294        public void invalidateAppearance()
     295        {
     296                AxisAlignedBoxBounds bounds = getBounds();
     297               
     298                if (bounds == null) return;
     299               
     300                if (_borderColour != null && _borderStroke != null && _borderStroke.thickness > 0) { // border
     301                        DisplayController.invalidateArea(ItemUtils.expandRectangle(bounds, (int)Math.ceil(getBorderThickness()) + 1));
    244302                } else { // no border
    245                         FrameGraphics.invalidateArea(getBounds());
    246                 }
    247 
    248         }
    249        
    250 
    251        
     303                        DisplayController.invalidateArea(bounds);
     304                }
     305
     306        }
    252307}
Note: See TracChangeset for help on using the changeset viewer.