Changeset 28


Ignore:
Timestamp:
05/14/08 09:32:42 (16 years ago)
Author:
ra33
Message:
 
Location:
trunk/src/org/expeditee/items
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/expeditee/items/InteractiveWidget.java

    r11 r28  
    2424 *
    2525 * @author Brook
    26  *
     26 * 
    2727 */
    2828public abstract class InteractiveWidget {
    2929
    3030        protected JComponent _component;
    31        
     31
    3232        /** A widget is comprised of dots and lines that basically form a rectangle */
    3333        private WidgetCorner _d1, _d2, _d3, _d4;
     34
    3435        private WidgetEdge _l1, _l2, _l3, _l4;
     36
    3537        /* GUIDE:
    3638         *                       l1
     
    4345         */
    4446        private List<Item> _items; // used for quickly returning item list
    45        
     47
    4648        // Widget size restrictions
    4749        private int _minWidth = 50;
     50
    4851        private int _minHeight = 50;
     52
    4953        private int _maxWidth = 300;
     54
    5055        private int _maxHeight = 300;
    51        
    52         // The Expeditee item that is used for saving widget state in expiditee world
     56
     57        // The Expeditee item that is used for saving widget state in expiditee
     58        // world
    5359        private Text _source;
    54        
     60
     61        // A flag for signifying whether the swing components are ready to paint.
     62        // If the swing components has not been layed out, if they are painted they
     63        // will
     64        // not draw in the correct positions.
     65        private boolean _isReadyToPaint = false;
     66
    5567        /**
    5668         * Creates a InteractiveWidget from a text item.
    5769         *
    58          * @param source Must not be null, first line of text used - which the format must
    59          *      be as follows: "@iw <<widget_class_name>> [<<width>>] [<<height>>] [: [<<arg1>>] [<<arg2>>] [...]]".
    60          *
    61          * e.g: "@iw org.expeditee.items.SampleWidget1 100 20 : 2"
    62          *              creates a SampleWidget1 with width = 100 and height = 20 with 1 argument = "2"
    63          *
     70         * @param source
     71         *            Must not be null, first line of text used - which the format
     72         *            must be as follows: "@iw <<widget_class_name>> [<<width>>] [<<height>>] [: [<<arg1>>] [<<arg2>>]
     73         *            [...]]".
     74         *
     75         * e.g: "@iw org.expeditee.items.SampleWidget1 100 20 : 2" creates a
     76         * SampleWidget1 with width = 100 and height = 20 with 1 argument = "2"
     77         *
    6478         * @return An InteractiveWidget instance. Never null.
    6579         *
    66          * @throws NullPointerException 
    67          *                              if source is null
    68          *
    69          * @throws IllegalArgumentException 
    70          *                              if source's text is in the incorrect format
    71          *                              or if source's parent is null
    72          *
    73          * @throws InteractiveWidgetNotAvailableException 
    74          *                              If the given widget class name in the source text
    75          *                              doesn't exist or not an InteractiveWidget or the widget
    76          *                              does not supply a valid constructor for creation.
     80         * @throws NullPointerException
     81         *             if source is null
     82         *
     83         * @throws IllegalArgumentException
     84         *             if source's text is in the incorrect format or if source's
     85         *             parent is null
     86         *
     87         * @throws InteractiveWidgetNotAvailableException
     88         *             If the given widget class name in the source text doesn't
     89         *             exist or not an InteractiveWidget or the widget does not
     90         *             supply a valid constructor for creation.
    7791         *
    7892         * Note: could throw other exceptions depending on the type of widget being
    7993         * instantainiated. source must have a parent
    8094         *
    81          * class names beginning with $, the $ will be replaced with "org.expeditee.items."
    82          */
    83         public static InteractiveWidget CreateWidget(Text source)
    84                 throws InteractiveWidgetNotAvailableException {
    85                
    86                 if (source == null) throw new NullPointerException("source");
    87                 if (source.getParent() == null)
    88                         throw new IllegalArgumentException("source's parent is null, InteractiveWidget's must be created from Text items with non-null parents");
     95         * class names beginning with $, the $ will be replaced with
     96         * "org.expeditee.items."
     97         */
     98        public static InteractiveWidget CreateWidget(Text source)
     99                        throws InteractiveWidgetNotAvailableException {
     100
     101                if (source == null)
     102                        throw new NullPointerException("source");
     103                if (source.getParent() == null)
     104                        throw new IllegalArgumentException(
     105                                        "source's parent is null, InteractiveWidget's must be created from Text items with non-null parents");
    89106
    90107                String TAG = ItemUtils.GetTag(ItemUtils.TAG_IWIDGET);
    91                
    92                
     108
    93109                String text = source.getTextNoList();
    94                 if (text == null) throw new IllegalArgumentException("source does not have any text");
    95                
    96                 int index = text.indexOf(':'); // used for signifying start of arguments
    97                 if (index == 0) throw new IllegalArgumentException("Source text must begin with \"" + TAG + "\"");
    98                
    99                 String[] tokens = (index == -1) ?
    100                                 text.split("\\s+") : text.substring(0,index).split(" ");
    101                
     110                if (text == null)
     111                        throw new IllegalArgumentException("source does not have any text");
     112
     113                int index = text.indexOf(':'); // used for signifying start of
     114                                                                                // arguments
     115                if (index == 0)
     116                        throw new IllegalArgumentException("Source text must begin with \""
     117                                        + TAG + "\"");
     118
     119                String[] tokens = (index == -1) ? text.split("\\s+") : text.substring(
     120                                0, index).split(" ");
     121
    102122                // Check starts with the widget tag
    103123                if (tokens.length < 1 || !tokens[0].equals(TAG))
    104                         throw new IllegalArgumentException("Source text must begin with \"" + TAG + "\"");
     124                        throw new IllegalArgumentException("Source text must begin with \""
     125                                        + TAG + "\"");
    105126
    106127                int width = -1, height = -1;
    107                
     128
    108129                if (tokens.length < 2)
    109                         throw new IllegalArgumentException("Missing widget class name in source text");
    110                
     130                        throw new IllegalArgumentException(
     131                                        "Missing widget class name in source text");
     132
    111133                try {
    112                        
     134
    113135                        if (tokens.length >= 3) { // parse optional width
    114136                                width = Integer.parseInt(tokens[2]);
    115137                                width = (width <= 0) ? width = -1 : width;
    116138                        }
    117                        
     139
    118140                        if (tokens.length >= 4) { // parse optional height
    119141                                height = Integer.parseInt(tokens[3]);
    120142                                height = (height <= 0) ? height = -1 : height;
    121143                        }
    122                        
     144
    123145                } catch (NumberFormatException nfe) {
    124                         throw new IllegalArgumentException("Bad width or height given in source text", nfe);
    125                 }
    126                
     146                        throw new IllegalArgumentException(
     147                                        "Bad width or height given in source text", nfe);
     148                }
     149
    127150                if (tokens.length > 4)
    128                         throw new IllegalArgumentException("to many arguments given before \":\" in source text");
    129                
     151                        throw new IllegalArgumentException(
     152                                        "to many arguments given before \":\" in source text");
     153
    130154                String classname = tokens[1];
    131                 if (classname.charAt(0) == '$') classname = "org.expeditee.items." + classname.substring(1);
    132                 // Attempt to locate the class  using reflection
    133                 Class iwclass = findIWidgetClass(classname);
    134                
     155                if (classname.charAt(0) == '$')
     156                        classname = "org.expeditee.items." + classname.substring(1);
     157                // Attempt to locate the class using reflection
     158                Class<?> iwclass = findIWidgetClass(classname);
     159
    135160                if (iwclass == null) // ensure it exists
    136                         throw new InteractiveWidgetNotAvailableException(classname + " does not exit or is not an InteractiveWidget");
    137                
     161                        throw new InteractiveWidgetNotAvailableException(classname
     162                                        + " does not exit or is not an InteractiveWidget");
     163
    138164                // Extract out the parameters - if any
    139165                String[] args = null;
    140166                if (index > 0) { // index of the first ":"
    141                         args = (text.length() == (index + 1)) ?
    142                                         null : parseArgs(text.substring(index + 1));
     167                        args = (text.length() == (index + 1)) ? null : parseArgs(text
     168                                        .substring(index + 1));
    143169                }
    144170
     
    146172                try {
    147173                        // Instantainiate the widget - passing the params
    148                         Class parameterTypes[] = new Class[] {Text.class, String[].class};
     174                        Class parameterTypes[] = new Class[] { Text.class, String[].class };
    149175                        Constructor ct = iwclass.getConstructor(parameterTypes);
    150                        
    151                         Object arglist[] = new Object[] {
    152                                 source,
    153                                 args
    154                         };
    155                        
    156                         inst = (InteractiveWidget)ct.newInstance(arglist);
     176
     177                        Object arglist[] = new Object[] { source, args };
     178
     179                        inst = (InteractiveWidget) ct.newInstance(arglist);
    157180                } catch (Exception e) {
    158                         throw new InteractiveWidgetNotAvailableException("Failed to create instance via reflection: " + e.toString(), e);
    159                 }
    160        
    161                 // Use default dimensions if not provided (or provided as negitive values)
    162                 if (width <= 0) width = inst.getWidth();
    163                 if (height <= 0) height = inst.getHeight();
    164                
     181                        throw new InteractiveWidgetNotAvailableException(
     182                                        "Failed to create instance via reflection: " + e.toString(),
     183                                        e);
     184                }
     185
     186                // Use default dimensions if not provided (or provided as negitive
     187                // values)
     188                if (width <= 0)
     189                        width = inst.getWidth();
     190                if (height <= 0)
     191                        height = inst.getHeight();
     192
    165193                inst.setSize(width, height);
    166                
     194
    167195                return inst;
    168196        }
    169        
     197
    170198        /**
    171199         * Locates the class from the classname of an InteractiveWidget class
    172          * @param classname The name of the class to search
     200         *
     201         * @param classname
     202         *            The name of the class to search
    173203         * @return Null if doesn't exist or not an InteractiveWidget
    174204         */
     
    176206                try {
    177207                        Class c = Class.forName(classname); // attempt to find the class
    178                        
    179                         // If one is found, ensure that it is a descendant of an InteractiveWidget
    180                         for (Class superclass = c.getSuperclass();
    181                                 superclass != null && superclass != Item.class;
    182                                 superclass = superclass.getSuperclass()) {
    183                                 if (superclass == InteractiveWidget.class) return c;
    184                         }
    185                        
    186                 } catch (ClassNotFoundException e) {}
    187                
     208
     209                        // If one is found, ensure that it is a descendant of an
     210                        // InteractiveWidget
     211                        for (Class superclass = c.getSuperclass(); superclass != null
     212                                        && superclass != Item.class; superclass = superclass
     213                                        .getSuperclass()) {
     214                                if (superclass == InteractiveWidget.class)
     215                                        return c;
     216                        }
     217
     218                } catch (ClassNotFoundException e) {
     219                }
     220
    188221                // Doesn't exist or not an InteractiveWidget
    189222                return null;
    190223        }
    191        
    192         /**
    193          * Using Microsofts commandline convention: Args seperated with white spaces.
    194          * Options with white spaces enclosed with quotes. Args with quotes must be double quoted
    195          * args1 args2=sfasas args3="option with spaces" arg""4""
    196          *
    197          * @param args Null and empty excepted
     224
     225        /**
     226         * Using Microsofts commandline convention: Args seperated with white
     227         * spaces. Options with white spaces enclosed with quotes. Args with quotes
     228         * must be double quoted args1 args2=sfasas args3="option with spaces"
     229         * arg""4""
     230         *
     231         * @param args
     232         *            Null and empty excepted
    198233         * @return An array of args. null if none provided
    199234         */
    200235        static String[] parseArgs(String args) {
    201                
    202                 if (args == null) return null;
    203                
     236
     237                if (args == null)
     238                        return null;
     239
    204240                args = args.trim();
    205                 if (args.length() == 0) return null;
    206 
    207                 List <String> vargs = new LinkedList<String>();
     241                if (args.length() == 0)
     242                        return null;
     243
     244                List<String> vargs = new LinkedList<String>();
    208245                StringBuilder sb = new StringBuilder();
    209246                boolean quoteOn = false;
    210247                for (int i = 0; i < args.length(); i++) {
    211                        
     248
    212249                        char c = args.charAt(i);
    213250                        if (c == ' ' && !quoteOn) {
    214                                
     251
    215252                                // Extract arg
    216253                                vargs.add(sb.toString());
    217254                                sb = new StringBuilder();
    218                                
     255
    219256                                // Consume white spaces
    220                                 while (args.charAt(++i) == ' ' && i < args.length()) { }
     257                                while (args.charAt(++i) == ' ' && i < args.length()) {
     258                                }
    221259                                i--;
    222                                
     260
    223261                        } else if (c == '\"') {
    224262                                // If double qouted
    225                                 if (args.length() >= (i + 2) &&
    226                                                 args.charAt(i + 1) == '\"') {
    227                                        
     263                                if (args.length() >= (i + 2) && args.charAt(i + 1) == '\"') {
     264
    228265                                        sb.append(c); // add escaped
    229                                         i ++;
    230                                        
     266                                        i++;
     267
    231268                                } else {
    232269                                        quoteOn = !quoteOn;
    233270                                }
    234                                
     271
    235272                        } else {
    236273                                sb.append(c);
    237274                        }
    238275                }
    239                
    240                 if (sb.length() > 0) vargs.add(sb.toString());
    241                
    242                 if (vargs.size() == 0) return null;
    243                 else return vargs.toArray(new String[vargs.size()]);
    244         }
    245        
     276
     277                if (sb.length() > 0)
     278                        vargs.add(sb.toString());
     279
     280                if (vargs.size() == 0)
     281                        return null;
     282                else
     283                        return vargs.toArray(new String[vargs.size()]);
     284        }
     285
    246286        /**
    247287         * Reverse of parseArgs
     288         *
    248289         * @return Null if args is null or empty / all whitespace
    249290         */
    250291        static String formatArgs(String[] args) {
    251                 if (args == null) return null;
    252                
     292                if (args == null)
     293                        return null;
     294
    253295                StringBuilder sb = new StringBuilder();
    254                
     296
    255297                for (String s : args) {
    256                         if (s == null) continue;
    257                        
     298                        if (s == null)
     299                                continue;
     300
    258301                        // Escape quotes
    259                         StringBuilder formatted = new StringBuilder(s.replaceAll("\"", "\"\""));
     302                        StringBuilder formatted = new StringBuilder(s.replaceAll("\"",
     303                                        "\"\""));
    260304
    261305                        // Encapsulate spaces
     
    265309                                formatted.append('\"');
    266310                        }
    267                        
    268                         if (sb.length() > 0) sb.append(' ');
     311
     312                        if (sb.length() > 0)
     313                                sb.append(' ');
    269314                        sb.append(formatted);
    270315                }
    271                
     316
    272317                return sb.length() > 0 ? sb.toString() : null;
    273318        }
    274        
    275         /**
    276          * Arguments represent state. They are used for saving, loading, creating and cloning
    277          * Special formatting is done for you.
    278          *     
    279          * @return Can be null for no params.
    280          */
    281         protected abstract String[] getArgs();
    282        
     319
     320        /**
     321         * Arguments represent state. They are used for saving, loading, creating
     322         * and cloning Special formatting is done for you.
     323         *
     324         * @param isCopy
     325         *            If true, then the requested arguments returned should
     326         *            represent a copy of this instance Otherwise the arguments
     327         *            returned should represent this instance. This gives the widget
     328         *            the chance to allocate new/duplicate resources if they need
     329         *            to.
     330         *
     331         * @return Can be null for no params.
     332         */
     333        protected abstract String[] getArgs(boolean isCopy);
     334
    283335        /**
    284336         * Constructor
    285          * @param source Must not be null. Neither must it's parent
    286          * @param component Must not be null
    287          */
    288         protected InteractiveWidget(Text source, JComponent component, int minWidth,
    289                         int maxWidth, int minHeight, int maxHeight) {
    290 
    291                 if (component == null) throw new NullPointerException("component");
    292                 if (source == null) throw new NullPointerException("source");
    293                 if (source.getParent() == null)
    294                         throw new IllegalArgumentException("source's parent is null, InteractiveWidget's must be created from Text items with non-null parents");
    295                
     337         *
     338         * @param source
     339         *            Must not be null. Neither must it's parent
     340         * @param component
     341         *            Must not be null
     342         */
     343        protected InteractiveWidget(Text source, JComponent component,
     344                        int minWidth, int maxWidth, int minHeight, int maxHeight) {
     345
     346                if (component == null)
     347                        throw new NullPointerException("component");
     348                if (source == null)
     349                        throw new NullPointerException("source");
     350                if (source.getParent() == null)
     351                        throw new IllegalArgumentException(
     352                                        "source's parent is null, InteractiveWidget's must be created from Text items with non-null parents");
     353
    296354                _component = component;
    297355                _source = source;
    298                
     356
    299357                _minWidth = minWidth;
    300358
    301                 if (maxWidth < _minWidth && maxWidth >= 0)
    302                         throw new IllegalArgumentException("maxWidth smaller than the min Width");
     359                if (maxWidth < _minWidth && maxWidth >= 0)
     360                        throw new IllegalArgumentException(
     361                                        "maxWidth smaller than the min Width");
    303362                _maxWidth = maxWidth;
    304363
    305364                _minHeight = minHeight;
    306                 if (maxHeight < _minHeight && maxHeight >= 0)
    307                         throw new IllegalArgumentException("maxHeight smaller than the min Height");
     365                if (maxHeight < _minHeight && maxHeight >= 0)
     366                        throw new IllegalArgumentException(
     367                                        "maxHeight smaller than the min Height");
    308368                _maxHeight = maxHeight;
    309        
    310        
     369
    311370                int x = source.getX();
    312371                int y = source.getY();
    313372                int width = (_minWidth < 0) ? 10 : _minWidth;
    314373                int height = (_minHeight < 0) ? 10 : _minHeight;
    315                
     374
    316375                Frame idAllocator = _source.getParent();
    317                
     376
    318377                // create WidgetCorners
    319378                _d1 = new WidgetCorner(x, y, idAllocator.getNextItemID(), this);
    320379                _d2 = new WidgetCorner(x + width, y, idAllocator.getNextItemID(), this);
    321                 _d3 = new WidgetCorner(x + width, y + height, idAllocator.getNextItemID(), this);
     380                _d3 = new WidgetCorner(x + width, y + height, idAllocator
     381                                .getNextItemID(), this);
    322382                _d4 = new WidgetCorner(x, y + height, idAllocator.getNextItemID(), this);
    323383
     
    336396                _items.add(_l2);
    337397                _items.add(_l3);
    338                 _items.add(_l4);       
     398                _items.add(_l4);
    339399        }
    340400
     
    342402         * @return A copy of this widget
    343403         */
    344         public abstract InteractiveWidget copy() throws InteractiveWidgetNotAvailableException;
     404        public final InteractiveWidget copy()
     405                        throws InteractiveWidgetNotAvailableException {
     406
     407                Text t = _source.copy();
     408                String clonedAnnotation = getAnnotationString(true);
     409                _source.setText(clonedAnnotation);
     410                return InteractiveWidget.CreateWidget(t);
     411        }
    345412
    346413        /**
     
    348415         */
    349416        protected abstract String getTopMostClassName();
    350        
     417
    351418        /**
    352419         * Note updates the source text with current state info
     420         *
    353421         * @return The Text item that this widget was created from.
    354422         */
    355423        public Text getSource() {
    356424
    357                 StringBuilder sb = new StringBuilder(ItemUtils.GetTag(ItemUtils.TAG_IWIDGET));
     425                // Build the annotation string such that it represents this widgets
     426                // current state
     427                String newAnnotation = getAnnotationString(false);
     428
     429                // Set the new text
     430                _source.setText(newAnnotation);
     431
     432                return _source;
     433        }
     434
     435        /**
     436         * @param copiedVersion
     437         *            True to return a copied representation of this instance. False
     438         *            to return this instances current state version.
     439         *
     440         * @return The expeditee anotation string.
     441         */
     442        private String getAnnotationString(boolean copiedVersion) {
     443
     444                // Create tag and append classname
     445                StringBuilder sb = new StringBuilder(ItemUtils
     446                                .GetTag(ItemUtils.TAG_IWIDGET));
    358447                sb.append(' ');
    359448                sb.append(getTopMostClassName());
    360                 sb.append(' ');
     449
     450                // Append size information if needed (not an attibute of text items)
    361451                if (!isFixedSize()) {
     452                        sb.append(' ');
    362453                        sb.append(getWidth());
    363454                        sb.append(' ');
    364455                        sb.append(getHeight());
    365                         sb.append(' ');
    366                 }
    367                
    368                 // Append new tags
    369                 String stateArgs = InteractiveWidget.formatArgs(getArgs());
     456                }
     457
     458                // Append arguments if any
     459                String stateArgs = InteractiveWidget.formatArgs(getArgs(copiedVersion));
    370460                if (stateArgs != null) {
    371461                        sb.append(':');
    372462                        sb.append(stateArgs);
    373463                }
    374                
    375                 // Set the new text
    376                 _source.setText(sb.toString());
    377 
    378                 return _source;
    379         }
    380        
     464
     465                return sb.toString();
     466        }
     467
    381468        /**
    382469         * Clamped to current min/max width/height.
     470         *
    383471         * @param width
    384472         * @param height
    385473         */
    386474        public void setSize(int width, int height) {
    387                
     475
    388476                // Clamp
    389                 if (width < _minWidth && _minWidth >= 0) width = _minWidth;
    390                 else if (width > _maxWidth && _maxWidth >= 0) width = _maxWidth;
    391                
    392                 if (height < _minHeight && _minHeight >= 0) height = _minHeight;
    393                 else if (height > _maxHeight && _maxHeight >= 0) height = _maxHeight;
    394                
    395                 boolean vfloating[] = new boolean[] {
    396                                 _d1.isFloating(),
    397                                 _d2.isFloating(),
    398                                 _d3.isFloating(),
    399                                 _d4.isFloating()
    400                         };
    401                        
    402                         _d1.setFloating(true);
    403                         _d2.setFloating(true);
    404                         _d3.setFloating(true);
    405                         _d4.setFloating(true);
    406                        
    407                         int x = _d1.getX() + width;
    408                         int y = _d1.getY() + height;
    409                         _d2.setX(x);
    410                         _d3.setX(x);
    411                         _d3.setY(y);
    412                         _d4.setY(y);
    413                        
    414                         _d1.setFloating(vfloating[0]);
    415                         _d2.setFloating(vfloating[1]);
    416                         _d3.setFloating(vfloating[2]);
    417                         _d4.setFloating(vfloating[3]);
    418 
    419         }
    420 
    421 
    422        
    423         public void setPosition(int x, int y) {
    424                
    425                 boolean vfloating[] = new boolean[] {
    426                         _d1.isFloating(),
    427                         _d2.isFloating(),
    428                         _d3.isFloating(),
    429                         _d4.isFloating()
    430                 };
    431                
    432                 int width = getWidth();
    433                 int height = getHeight();
    434                
     477                if (width < _minWidth && _minWidth >= 0)
     478                        width = _minWidth;
     479                else if (width > _maxWidth && _maxWidth >= 0)
     480                        width = _maxWidth;
     481
     482                if (height < _minHeight && _minHeight >= 0)
     483                        height = _minHeight;
     484                else if (height > _maxHeight && _maxHeight >= 0)
     485                        height = _maxHeight;
     486
     487                boolean vfloating[] = new boolean[] { _d1.isFloating(),
     488                                _d2.isFloating(), _d3.isFloating(), _d4.isFloating() };
     489
    435490                _d1.setFloating(true);
    436491                _d2.setFloating(true);
    437492                _d3.setFloating(true);
    438493                _d4.setFloating(true);
    439                
     494
     495                int x = _d1.getX() + width;
     496                int y = _d1.getY() + height;
     497                _d2.setX(x);
     498                _d3.setX(x);
     499                _d3.setY(y);
     500                _d4.setY(y);
     501
     502                _d1.setFloating(vfloating[0]);
     503                _d2.setFloating(vfloating[1]);
     504                _d3.setFloating(vfloating[2]);
     505                _d4.setFloating(vfloating[3]);
     506
     507        }
     508
     509        public void setPosition(int x, int y) {
     510
     511                boolean vfloating[] = new boolean[] { _d1.isFloating(),
     512                                _d2.isFloating(), _d3.isFloating(), _d4.isFloating() };
     513
     514                int width = getWidth();
     515                int height = getHeight();
     516
     517                _d1.setFloating(true);
     518                _d2.setFloating(true);
     519                _d3.setFloating(true);
     520                _d4.setFloating(true);
     521
    440522                _d1.setPosition(x, y);
    441523                _d2.setPosition(x + width, y);
    442524                _d3.setPosition(x + width, y + height);
    443525                _d4.setPosition(x, y + height);
    444                
     526
    445527                _d1.setFloating(vfloating[0]);
    446528                _d2.setFloating(vfloating[1]);
     
    449531
    450532        }
    451        
     533
    452534        private boolean _settingPositionFlag = false; // used for recursion
    453        
     535
    454536        /**
    455537         * to be called from corners only
     538         *
    456539         * @param src
    457540         * @param x
     
    460543         */
    461544        boolean setPositions(WidgetCorner src, int x, int y) {
    462                
    463                 if (_settingPositionFlag) return false;
     545
     546                if (_settingPositionFlag)
     547                        return false;
    464548                _settingPositionFlag = true;
    465                
     549
     550                // Check to see if the widget is fully being picked up
     551                boolean isAllPickedUp = (_d1.isFloating() && _d2.isFloating()
     552                                && _d3.isFloating() && _d4.isFloating());
     553
    466554                int newX = x;
    467                
     555
    468556                // X Positions
    469557                if (src == _d1 || src == _d4) {
    470                        
    471                         // Note: the isFloating test is an indication to whether or not
    472                         // the widgets rectangle is being fully picked up... if it is then
    473                         // tere is no need to specially enforce constraints because they will
    474                         // all be moved togather with same relative positions.
    475                         if (src == _d1 && _d4.isFloating()) _d1.setX(newX);
    476                         else if (src == _d4 && _d1.isFloating())  _d4.setX(newX);
     558
     559                        if (src == _d1 && isAllPickedUp)
     560                                _d1.setX(newX);
     561                        else if (src == _d4 && isAllPickedUp)
     562                                _d4.setX(newX);
    477563                        else {
    478564                                // Check min X constraint
    479565                                if (_minWidth >= 0) {
    480566                                        if ((_d2.getX() - x) < _minWidth) {
    481                                                 newX =  _d2.getX() - _minWidth;
     567                                                newX = _d2.getX() - _minWidth;
    482568                                        }
    483569                                }
     
    485571                                if (_maxWidth >= 0) {
    486572                                        if ((_d2.getX() - x) > _maxWidth) {
    487                                                 newX =  _d2.getX() - _maxWidth;
     573                                                newX = _d2.getX() - _maxWidth;
    488574                                        }
    489575                                }
    490                                
    491                                 _d1.setX(newX);
    492                                 _d4.setX(newX);
    493                         }
    494                        
     576
     577                                if (!(src == _d4 && _d1.isFloating() && _d4.isFloating()))
     578                                        _d1.setX(newX);
     579                                if (!(src == _d1 && _d4.isFloating() && _d1.isFloating()))
     580                                        _d4.setX(newX);
     581                        }
     582
    495583                } else if (src == _d2 || src == _d3) {
    496                        
    497                         if (src == _d2 && _d3.isFloating()) _d2.setX(newX);
    498                         else if (src == _d3 && _d2.isFloating()) _d3.setX(newX);
     584
     585                        if (src == _d2 && isAllPickedUp)
     586                                _d2.setX(newX);
     587                        else if (src == _d3 && isAllPickedUp)
     588                                _d3.setX(newX);
    499589                        else {
    500590                                // Check min X constraint
     
    507597                                if (_maxWidth >= 0) {
    508598                                        if ((x - _d1.getX()) > _maxWidth) {
    509                                                 newX =  _d1.getX() + _maxWidth;
     599                                                newX = _d1.getX() + _maxWidth;
    510600                                        }
    511601                                }
    512                                
    513                                 _d2.setX(newX);
    514                                 _d3.setX(newX);
    515                         }
    516                        
    517                 }
    518                
     602
     603                                if (!(src == _d3 && _d2.isFloating() && _d3.isFloating()))
     604                                        _d2.setX(newX);
     605                                if (!(src == _d2 && _d3.isFloating() && _d2.isFloating()))
     606                                        _d3.setX(newX);
     607                        }
     608
     609                }
     610
    519611                int newY = y;
    520                
     612
    521613                // Y Positions
    522614                if (src == _d1 || src == _d2) {
    523                        
    524                         if (src == _d1 && _d2.isFloating()) _d1.setY(newY);
    525                         else if (src == _d2 && _d1.isFloating())  _d2.setY(newY);
     615
     616                        if (src == _d1 && isAllPickedUp)
     617                                _d1.setY(newY);
     618                        else if (src == _d2 && isAllPickedUp)
     619                                _d2.setY(newY);
    526620                        else {
    527621                                // Check min Y constraint
    528622                                if (_minHeight >= 0) {
    529623                                        if ((_d4.getY() - y) < _minHeight) {
    530                                                 newY =  _d4.getY() - _minHeight;
     624                                                newY = _d4.getY() - _minHeight;
    531625                                        }
    532626                                }
     
    534628                                if (_maxHeight >= 0) {
    535629                                        if ((_d4.getY() - y) > _maxHeight) {
    536                                                 newY =  _d4.getY() - _maxHeight;
     630                                                newY = _d4.getY() - _maxHeight;
    537631                                        }
    538632                                }
    539                                 _d1.setY(newY);
    540                                 _d2.setY(newY);
    541                         }
    542                        
     633
     634                                if (!(src == _d2 && _d1.isFloating() && _d2.isFloating()))
     635                                        _d1.setY(newY);
     636                                if (!(src == _d1 && _d2.isFloating() && _d1.isFloating()))
     637                                        _d2.setY(newY);
     638
     639                        }
     640
    543641                } else if (src == _d3 || src == _d4) {
    544                        
    545                         if (src == _d3 && _d4.isFloating()) _d3.setY(newY);
    546                         else if (src == _d4 && _d3.isFloating())  _d4.setY(newY);
     642
     643                        if (src == _d3 && isAllPickedUp)
     644                                _d3.setY(newY);
     645                        else if (src == _d4 && isAllPickedUp)
     646                                _d4.setY(newY);
    547647                        else {
    548648                                // Check min Y constraint
     
    555655                                if (_maxHeight >= 0) {
    556656                                        if ((y - _d1.getY()) > _maxHeight) {
    557                                                 newY =  _d1.getY() + _maxHeight;
     657                                                newY = _d1.getY() + _maxHeight;
    558658                                        }
    559659                                }
    560                                
    561                                 _d3.setY(newY);
    562                                 _d4.setY(newY);
    563                         }
    564                 }
    565                
    566                 // Update source text position so position is remembered from loading
     660
     661                                if (!(src == _d4 && _d3.isFloating() && _d4.isFloating()))
     662                                        _d3.setY(newY);
     663                                if (!(src == _d3 && _d4.isFloating() && _d3.isFloating()))
     664                                        _d4.setY(newY);
     665                        }
     666                }
     667
     668                // Update source text position so position is remembered from loading
    567669                int newTextX = getX();
    568670                int newTextY = getY();
    569671                if (_source.getX() != newTextX || _source.getY() != newTextY)
    570672                        _source.setPosition(newTextX, newTextY);
    571                
     673
    572674                _settingPositionFlag = false;
    573675                return true;
    574676        }
    575        
     677
    576678        public int getX() {
    577679                return Math.min(_d1.getX(), _d2.getX());
    578680        }
    579        
     681
    580682        public int getY() {
    581683                return Math.min(_d1.getY(), _d4.getY());
    582684        }
    583        
     685
    584686        public int getWidth() {
    585687                return Math.abs(_d2.getX() - _d1.getX());
    586688        }
    587        
     689
    588690        public int getHeight() {
    589691                return Math.abs(_d4.getY() - _d1.getY());
    590692        }
    591        
    592         /**
    593          * The order of the items in the list is as specified:
    594                 _d1
    595                 _d2
    596                 _d3
    597                 _d4
    598                 _l1
    599                 _l2
    600                 _l3
    601                 _l4
    602          * @return All of the Expeditee items that form the bounderies of this widget
    603          * in an unmodifiable list
     693
     694        /**
     695         * The order of the items in the list is as specified: _d1 _d2 _d3 _d4 _l1
     696         * _l2 _l3 _l4
     697         *
     698         * @return All of the Expeditee items that form the bounderies of this
     699         *         widget in an unmodifiable list
    604700         */
    605701        public List<Item> getItems() {
    606702                return Collections.unmodifiableList(_items);
    607703        }
    608        
    609704
    610705        public JComponent getComponant() {
    611706                return _component;
    612707        }
    613        
    614         public final void onParentFameHidden() {
    615                 onRemovedFromFrame();
    616         }
    617 
    618         public final void onParentFameShown() {
    619                 onAddedToFrame();
    620         }
    621        
    622         public void onRemovedFromFrame() {
    623                 if (_component.getParent() != null) {
    624                         _component.getParent().remove(_component);
    625                 }
    626         }
    627        
    628         public void onAddedToFrame() {
    629                
    630                 if (_component.getParent() == null) {
    631                         if (Browser._theBrowser != null) {
    632                                 // Due to precaching - before adding physical swing componant must check
    633                                 // to see that this widget belongs to a frame that is considered current.
    634                                 if (_d1.getParent() == DisplayIO.getCurrentFrame()) {
    635                                         Browser._theBrowser.getContentPane().add(_component);
    636                                         layout(_component);
    637                                 }
    638                                
    639                         } else { // if widgets exist on startup frame this will occur
    640                                
    641                                 synchronized(_widgetsToAddLater) {
    642                                         _widgetsToAddLater.add(this);
    643                                 }
    644                                 SwingUtilities.invokeLater(new AddToFrameLater());
    645                         }
    646                 }
    647         }
    648        
    649         /**
    650          * Must be able to add widgets on first loaded frame: these are loaded before
    651          * the browser singleton is made available.
    652          */
    653         private static List<InteractiveWidget> _widgetsToAddLater = new LinkedList<InteractiveWidget>();
    654        
     708
     709        public final void onParentFameHidden(WidgetCorner notifier) {
     710                onRemovedFromFrame(notifier);
     711        }
     712
     713        public final void onParentFameShown(WidgetCorner notifier,
     714                        boolean isOverlayed, int overlayLevel) {
     715                addJComponantToFrame(notifier, isOverlayed, overlayLevel, true);
     716        }
     717
     718        public void onRemovedFromFrame(WidgetCorner notifier) {
     719                if (notifier == _d4) {
     720                        if (_component.getParent() != null) {
     721                                _component.getParent().remove(_component);
     722                        }
     723                }
     724        }
     725
     726        public void onAddedToFrame(WidgetCorner notifier, boolean isOverlayed,
     727                        int overlayLevel) {
     728                addJComponantToFrame(notifier, isOverlayed, overlayLevel, false);
     729        }
     730
     731        private void addJComponantToFrame(WidgetCorner notifier,
     732                        boolean isOverlayed, int overlayLevel, boolean isShown) {
     733                if (notifier == _d4) {
     734                        if (isOverlayed && overlayLevel == Item.PERMISSION_NONE)
     735                                return; // non-active overlays
     736
     737                        if (_component.getParent() == null) {
     738                                if (Browser._theBrowser != null) {
     739                                        // Due to precaching - before adding physical swing
     740                                        // componant must check
     741                                        // to see that this widget belongs to a frame that is
     742                                        // considered current.
     743                                        // If the widget is shown however this does not apply -
     744                                        // since it has been explicitly
     745                                        // made clear the the widget is shown.
     746                                        if (isShown
     747                                                        || _d1.getParent() == DisplayIO.getCurrentFrame()) {
     748                                                Browser._theBrowser.getContentPane().add(_component);
     749                                                layout(_component);
     750                                        }
     751
     752                                } else { // if widgets exist on startup frame this will occur
     753
     754                                        synchronized (_widgetsToAddLater) {
     755                                                _widgetsToAddLater.add(new WidgetInfo(notifier,
     756                                                                isOverlayed, overlayLevel, this));
     757                                        }
     758                                        SwingUtilities.invokeLater(new AddToFrameLater());
     759                                }
     760                        }
     761                }
     762        }
     763
     764        /**
     765         * Used for passing info to the swing thread
     766         *
     767         * @author Brook Novak
     768         */
     769        class WidgetInfo {
     770
     771                WidgetInfo(WidgetCorner notifier, boolean isOverlayed,
     772                                int overlayLevel, InteractiveWidget widget) {
     773                        _widget = widget;
     774                        _isOverlayed = isOverlayed;
     775                        _overlayLevel = overlayLevel;
     776                        _notifier = notifier;
     777                }
     778
     779                InteractiveWidget _widget;
     780
     781                boolean _isOverlayed;
     782
     783                int _overlayLevel;
     784
     785                WidgetCorner _notifier;
     786        }
     787
     788        /**
     789         * Must be able to add widgets on first loaded frame: these are loaded
     790         * before the browser singleton is made available.
     791         */
     792        private static List<WidgetInfo> _widgetsToAddLater = new LinkedList<WidgetInfo>();
     793
    655794        /**
    656795         * Ensures widgets are added correctly to first loaded frame
    657796         */
    658         public class AddToFrameLater implements Runnable {
     797        class AddToFrameLater implements Runnable {
    659798                public void run() {
    660799                        if (!_widgetsToAddLater.isEmpty()) {
    661                                 List<InteractiveWidget> tmp = null;
    662                                 synchronized(_widgetsToAddLater) {
    663                                         tmp = new LinkedList<InteractiveWidget>(_widgetsToAddLater);
     800                                List<WidgetInfo> tmp = null;
     801                                synchronized (_widgetsToAddLater) {
     802                                        tmp = new LinkedList<WidgetInfo>(_widgetsToAddLater);
    664803                                }
    665804                                _widgetsToAddLater.clear();
    666                                 for (InteractiveWidget iw : tmp) {
    667                                         iw.onAddedToFrame();
    668                                 }
    669                         }
    670                 }
    671         }
    672        
     805                                for (WidgetInfo iwi : tmp) {
     806                                        iwi._widget.onAddedToFrame(iwi._notifier, iwi._isOverlayed,
     807                                                        iwi._overlayLevel);
     808                                }
     809                        }
     810                }
     811        }
     812
    673813        /**
    674814         * Due to absolute positioning...
     815         *
    675816         * @param parent
    676817         */
    677818        private void layout(Component parent) {
    678                
     819
    679820                parent.doLayout();
    680                
     821
    681822                if (parent instanceof Container) {
    682                         for (Component c : ((Container)parent).getComponents()) {
    683                                
    684                                 if (c instanceof Container) layout(c);
    685                                 else c.doLayout();
    686                         }
    687                 }
    688         }
    689        
    690 
     823                        for (Component c : ((Container) parent).getComponents()) {
     824
     825                                if (c instanceof Container)
     826                                        layout(c);
     827                                else
     828                                        c.doLayout();
     829                        }
     830                }
     831
     832                _isReadyToPaint = true;
     833        }
    691834
    692835        public void onBoundsChanged() {
    693836
    694837                _component.setBounds(getX(), getY(), getWidth(), getHeight());
    695                
    696         }
    697        
     838
     839        }
     840
    698841        /**
    699842         * Paints the widget excluding the boundries. That is, the Swing graphics
     843         *
    700844         * @param g
    701845         */
    702846        public void paint(Graphics g) {
     847
     848                if (!_isReadyToPaint) {
     849                        layout(_component);
     850                }
    703851
    704852                Point loc = _component.getLocation();
     
    706854                _component.paint(g);
    707855                g.translate(-loc.x, -(loc.y - 1));
    708                
    709         }
    710        
    711         /**
    712          * Called from the widgets corners: Whenever the corners are repainted
    713          * and the widget is floating (e.g. currently picked up / rubberbanding)
    714          * then a shaded area is drawn instead of the actual widget so the manipulation of
    715          * the widget is as smooth as possible.
    716          * The shaded area is only draw once so it selects one of the 4 possible
    717          * notifiers to be the actual trigger to draw the shaded area
     856
     857        }
     858
     859        /**
     860         * Called from the widgets corners: Whenever the corners are repainted and
     861         * the widget is floating (e.g. currently picked up / rubberbanding) then a
     862         * shaded area is drawn instead of the actual widget so the manipulation of
     863         * the widget is as smooth as possible. The shaded area is only draw once so
     864         * it selects one of the 4 possible notifiers to be the actual trigger to
     865         * draw the shaded area
     866         *
    718867         * @param g
    719868         * @param notifier
     
    724873                        // paint over the widget interface in these cases: must only
    725874                        // paint if an object is floating
    726                         if (notifier == _d4 &&
    727                                         (_d1.isFloating() ||
    728                                         _d2.isFloating() ||
    729                                         _d3.isFloating() ||
    730                                         _d4.isFloating()
    731                                                         )) {
     875                        if (notifier == _d4
     876                                        && (_d1.isFloating() || _d2.isFloating()
     877                                                        || _d3.isFloating() || _d4.isFloating())) {
    732878                                g.setColor(Color.DARK_GRAY);
    733879                                g.fillRect(getX(), getY(), getWidth(), getHeight());
    734880                        }
    735                 } 
    736         }
    737        
     881                }
     882        }
     883
    738884        /**
    739885         * @return True if this widget cannot be resized in either directions
    740886         */
    741887        public boolean isFixedSize() {
    742                 return this._minHeight == this._maxHeight &&
    743                         this._minWidth == this._maxWidth &&
    744                         this._minHeight >= 0 &&
    745                         this._minWidth >= 0;
    746         }
    747        
     888                return this._minHeight == this._maxHeight
     889                                && this._minWidth == this._maxWidth && this._minHeight >= 0
     890                                && this._minWidth >= 0;
     891        }
     892
    748893        private static boolean _isExepiteeHighlightingEnabled = true;
     894
    749895        /**
    750896         * Enables/Disables highlighting of all widgets - if the enable value has
    751897         * changed the current frame will repaint.
    752898         *
    753          * The purpose of this is so that widgets can have an extra context:
    754          * no expeditee highlighting if focus is on a swing componet.
    755          *
    756          * @param enable Set to true to enable painting, false to disable painting.
     899         * The purpose of this is so that widgets can have an extra context: no
     900         * expeditee highlighting if focus is on a swing componet.
     901         *
     902         * @param enable
     903         *            Set to true to enable painting, false to disable painting.
    757904         */
    758905        public static void enableExepiteeHighlighting(boolean enable) {
     
    762909                }
    763910        }
    764        
     911
    765912        public static boolean isExepiteeHighlightingEnabled() {
    766913                return _isExepiteeHighlightingEnabled;
    767914        }
    768                
    769        
     915
    770916}
  • trunk/src/org/expeditee/items/SampleWidget1.java

    r11 r28  
    4949
    5050        @Override
    51         protected String[] getArgs() {
     51        protected String[] getArgs(boolean isCopy) {
    5252               
    5353                String[] stateArgs = new String[_combo.getItemCount() + 1];
     
    5858               
    5959                return stateArgs;
    60         }
    61 
    62         @Override
    63         public InteractiveWidget copy() throws InteractiveWidgetNotAvailableException {
    64                 Text t = this.getSource().copy();
    65                 return InteractiveWidget.CreateWidget(t);
    6660        }
    6761       
  • trunk/src/org/expeditee/items/SampleWidget2.java

    r11 r28  
    1212
    1313public class SampleWidget2 extends InteractiveWidget {
    14 
    1514       
    1615        private JComboBox _combo;
     
    7069                                        int div = Integer.parseInt(args[2]);
    7170                                        ((JSplitPane)super._component).setDividerLocation(div);
    72                                 } catch (NumberFormatException e) {
    73                                         e.printStackTrace();
    74                                 }
     71                                } catch (NumberFormatException e) {}
    7572                               
    7673                        }
     
    8178
    8279        @Override
    83         protected String[] getArgs() {
     80        protected String[] getArgs(boolean isCopy) {
    8481                return new String[] {
    8582                                Integer.toString(_combo.getSelectedIndex()),
     
    9087
    9188        @Override
    92         public InteractiveWidget copy() throws InteractiveWidgetNotAvailableException {
    93                 Text t = this.getSource().copy();
    94                 return InteractiveWidget.CreateWidget(t);
    95         }
    96        
    97         @Override
    9889        protected String getTopMostClassName() {
    9990                return getClass().getName();
  • trunk/src/org/expeditee/items/WidgetCorner.java

    r11 r28  
    3232        public void onParentFameHidden() {
    3333                super.onParentFameHidden();
    34                 _widgetSource.onParentFameHidden();
     34                _widgetSource.onParentFameHidden(this);
    3535        }
    3636
    3737        @Override
    38         public void onParentFameShown() {
    39                 super.onParentFameShown();
    40                 _widgetSource.onParentFameShown();
     38        public void onParentFameShown(boolean isOverlayed, int overlayLevel) {
     39                super.onParentFameShown(isOverlayed, overlayLevel);
     40                _widgetSource.onParentFameShown(this, isOverlayed, overlayLevel);
    4141        }
    4242
     
    4444        public void onRemovedFromFrame() {
    4545                super.onRemovedFromFrame();
    46                 _widgetSource.onRemovedFromFrame();
     46                _widgetSource.onRemovedFromFrame(this);
    4747        }
    4848
    4949        @Override
    50         public void onAddedToFrame() {
    51                 super.onAddedToFrame();
    52                 _widgetSource.onAddedToFrame();
     50        public void onAddedToFrame(boolean isOverlayed, int overlayLevel) {
     51                super.onAddedToFrame(isOverlayed, overlayLevel);
     52                _widgetSource.onAddedToFrame(this, isOverlayed, overlayLevel);
    5353        }
    5454
Note: See TracChangeset for help on using the changeset viewer.