Ignore:
Timestamp:
07/03/08 16:48:09 (16 years ago)
Author:
bjn8
Message:

Added invalidation for graphics... biiiig commit. LOts of effeciency improvements - now can animate

File:
1 edited

Legend:

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

    r115 r121  
    55import java.awt.Container;
    66import java.awt.Dimension;
    7 import java.awt.Font;
     7import java.awt.EventQueue;
    88import java.awt.Graphics;
    99import java.awt.Graphics2D;
     
    1111import java.awt.Image;
    1212import java.awt.Point;
     13import java.awt.Rectangle;
    1314import java.awt.RenderingHints;
     15import java.awt.geom.Area;
    1416import java.awt.image.BufferedImage;
    15 import java.awt.image.VolatileImage;
    1617import java.util.Collection;
    1718import java.util.Collections;
     
    2122import java.util.List;
    2223
     24import javax.swing.JComponent;
    2325import javax.swing.JPopupMenu;
    2426import javax.swing.SwingUtilities;
    2527
    26 import org.expeditee.actions.Misc;
    2728import org.expeditee.items.Circle;
    2829import org.expeditee.items.InteractiveWidget;
     
    3031import org.expeditee.items.ItemUtils;
    3132import org.expeditee.items.Line;
    32 import org.expeditee.items.Text;
    3333import org.expeditee.items.WidgetEdge;
    3434import org.expeditee.items.XRayable;
    3535
    3636public class FrameGraphics {
    37         public static final int MESSAGE_BUFFER_HEIGHT = 100;
    38 
    39         private static final int MESSAGE_LINK_Y_OFFSET = 100;
    40 
    41         private static final int MESSAGE_LINK_X = 50;
    4237
    4338        // the graphics used to paint with
     
    4742        private static Dimension _MaxSize;
    4843
    49         // messages shown in the message window
    50         public static Text[] Messages = new Text[4];
    51 
    52         // buffer of the message window
    53         private static VolatileImage _MessageBuffer = null;
    54 
    55         // font used for the messages
    56         private static Font _MessageFont = Font.decode("Serif-Plain-16");
    57 
    58         // the number of messages currently shown (used for scrolling up)
    59         private static int _MessageCount = 0;
    60 
    6144        // modes
    6245        public static final int MODE_NORMAL = 0;
     
    6548
    6649        public static final int MODE_XRAY = 2;
    67 
    68         public static final Color ERROR_COLOR = Color.red;
    6950
    7051        // Start in XRay mode so that errors arnt thrown when parsing the profile
    7152        // frame if it has images on it
    7253        private static int _Mode = MODE_XRAY;
    73 
    74         // if true, error messages are not shown to the user
    75         private static boolean _SupressMessages = false;
    76 
    77         public static String MESSAGES_FRAMESET_NAME = "Messages";
    78 
    79         // The link to the message frameset
    80         public static Item MessageLink = new Text(-2, "@" + MESSAGES_FRAMESET_NAME,
    81                         Color.black, Color.white);
    82 
    83         // creator for creating the message frames
    84         private static FrameCreator _creator;
     54       
     55        private FrameGraphics() {
     56                // util constructor
     57        }
    8558
    8659        /**
     
    10477                FrameUtils.Parse(current);
    10578                DisplayIO.UpdateTitle();
    106                 setMaxSize(new Dimension(_MaxSize.width, _MessageBuffer.getHeight()
     79                setMaxSize(new Dimension(_MaxSize.width, MessageBay.getMessageBufferHeight()
    10780                                + _MaxSize.height));
    108                 Repaint();
     81                refresh(false);
    10982        }
    11083
     
    12093                DisplayIO.UpdateTitle();
    12194                FrameMouseActions.getInstance().refreshHighlights();
    122                 Repaint();
     95                refresh(false);
    12396        }
    12497
     
    151124                // Hide the message buffer if in audience mode
    152125                int newMaxHeight = max.height
    153                                 - (isAudienceMode() ? 0 : MESSAGE_BUFFER_HEIGHT);
     126                                - (isAudienceMode() ? 0 : MessageBay.MESSAGE_BUFFER_HEIGHT);
    154127                if (newMaxHeight > 0) {
    155128                        _MaxSize.setSize(max.width, newMaxHeight);
     
    161134                }
    162135
    163                 if (newMaxHeight > 0) {
    164                         _MessageBuffer = null;
    165 
    166                         for (int i = 0; i < Messages.length; i++) {
    167                                 if (Messages[i] != null) {
    168                                         Messages[i].setOffset(0, -_MaxSize.height);
    169                                         Messages[i].setMaxSize(_MaxSize);
    170                                 }
    171                         }
    172 
    173                         MessageLink.setOffset(0, -_MaxSize.height);
    174                         MessageLink.setMaxSize(_MaxSize);
    175                         MessageLink.setPosition(_MaxSize.width - MESSAGE_LINK_Y_OFFSET,
    176                                         MESSAGE_LINK_X);
    177                 }
    178                 // Repaint();
     136                if (newMaxHeight > 0)
     137                        MessageBay.updateSize();
    179138        }
    180139
     
    205164         * Displays the given Item on the screen
    206165         */
    207         private static void PaintItem(Graphics2D g, Item i) {
     166        static void PaintItem(Graphics2D g, Item i) {
    208167                if (i == null || g == null)
    209168                        return;
     
    286245        }
    287246
    288         private static Image Paint(Frame toPaint) {
    289                 return Paint(toPaint, true);
    290         }
    291 
    292         private static Image Paint(Frame toPaint, boolean isActualFrame) {
     247        private static Image Paint(Frame toPaint, Area clip) {
     248                return Paint(toPaint, clip, true);
     249        }
     250
     251        /**
     252         *
     253         * @param toPaint
     254         * @param clip If null, then no clip applied.
     255         * @param isActualFrame
     256         * @return
     257         */
     258        private static Image Paint(Frame toPaint, Area clip, boolean isActualFrame) {
    293259                if (toPaint == null)
    294260                        return null;
     
    313279
    314280                        Graphics2D bg = (Graphics2D) buffer.getGraphics();
     281                        bg.setClip(clip);
     282                       
     283                        // TODO: Revise images and clip - VERY IMPORTANT
    315284
    316285                        // Nicer looking lines, but may be too jerky while
     
    331300                        }
    332301
     302                       
    333303                        bg.setColor(backgroundColor);
     304                        // bg.setColor(Color.pink); // TODO: TEMP FOR DEBUGGING
     305                       
    334306                        bg.fillRect(0, 0, _MaxSize.width, _MaxSize.height);
    335307
    336                         List<Item> paintItems = new LinkedList<Item>();
     308                        List<Item> visibleItems = new LinkedList<Item>();
    337309                        List<InteractiveWidget> paintWidgets;
    338310
     
    340312                                // Add all the items for this frame and any other from other
    341313                                // frames
    342                                 paintItems.addAll(toPaint.getAllItems());
    343 
     314                                visibleItems.addAll(toPaint.getAllItems());
    344315                                paintWidgets = new LinkedList<InteractiveWidget>();
    345316                                AddAllOverlayWidgets(paintWidgets, toPaint,
    346317                                                new LinkedList<Frame>());
    347318                        } else {
    348                                 paintItems.addAll(toPaint.getVisibleItems());
    349                                 paintItems.addAll(toPaint.getVectorItems());
     319                                visibleItems.addAll(toPaint.getVisibleItems());
     320                                visibleItems.addAll(toPaint.getVectorItems());
    350321                                paintWidgets = toPaint.getInteractiveWidgets();
    351322                        }
    352323
    353324                        // FIRST: Paint widgets swing gui (not expeditee gui) .
    354                         // Note that these are the ancored widgets
     325                        // Note that these are the anchored widgets
    355326                        for (InteractiveWidget iw : paintWidgets) {
    356                                 iw.paint(bg);
    357                         }
    358 
    359                         PaintPictures(bg, paintItems);
    360                         PaintLines(bg, paintItems);
    361 
     327                                if (clip == null || clip.intersects(iw.getComponant().getBounds()))
     328                                        iw.paint(bg);
     329                        }
     330                       
     331                        // Filter out items that do not need to be painted
     332                        List<Item> paintItems;
     333                        HashSet<Item> fillOnlyItems = null; // only contains items that do not need drawing but fills might
     334                       
     335                        if (clip == null) {
     336                                paintItems = visibleItems;
     337                        } else {
     338                                fillOnlyItems = new HashSet<Item>();
     339                                paintItems = new LinkedList<Item>();
     340                                for (Item i : visibleItems) {
     341                                        if (i.isInDrawingArea(clip)) {
     342                                                paintItems.add(i);
     343                                        } else if (i.isEnclosed()) {
     344                                                // just add all fill items despite possibility of fills not being in clip
     345                                                // because it will be faster than having to test twice for fills that do need
     346                                                // repainting.
     347                                                fillOnlyItems.add(i);
     348                                        }
     349                                }
     350                        }
     351                        // Only paint files and lines once ... between anchored AND free items
     352                        HashSet<Item> paintedFillsAndLines = new HashSet<Item> ();
     353                        PaintPictures(bg, paintItems, fillOnlyItems, paintedFillsAndLines);
     354                        PaintLines(bg, visibleItems);
     355
     356                        // Filter out free items that do not need to be painted
     357                        // This is efficient in cases with animation while free items exist
     358                       
     359                        List<Item> freeItemsToPaint = new LinkedList<Item>();
     360                        if (clip == null) {
     361                                freeItemsToPaint = FreeItems.getInstance();
     362                        } else {
     363                                freeItemsToPaint = new LinkedList<Item>();
     364                                fillOnlyItems.clear();
     365                                for (Item i : FreeItems.getInstance()) {
     366                                        if (i.isInDrawingArea(clip)) {
     367                                                freeItemsToPaint.add(i);
     368                                        } else if (i.isEnclosed()) {
     369                                                fillOnlyItems.add(i);
     370                                        }
     371                                }
     372                        }
     373                       
    362374                        if (isActualFrame /* && toPaint == DisplayIO.getCurrentFrame() */)
    363                                 PaintPictures(bg, Frame.FreeItems);
    364                         // TODO if we can get transparency with FreeItems... then text can
     375                                PaintPictures(bg, freeItemsToPaint, fillOnlyItems, paintedFillsAndLines);
     376                        // TODO if we can get transparency with FreeItems.getInstance()... then text can
    365377                        // be done before freeItems
    366378                        PaintNonLinesNonPicture(bg, paintItems);
     
    374386                        if (DisplayIO.isTwinFramesOn()) {
    375387                                List<Item> lines = new LinkedList<Item>();
    376                                 for (Item i : Frame.FreeItems) {
     388                                for (Item i : freeItemsToPaint) {
    377389                                        if (i instanceof Line) {
    378390                                                Line line = (Line) i;
     
    411423                                // Dont paint the
    412424                                if (isActualFrame)
    413                                         PaintLines(bg, Frame.FreeItems);
     425                                        PaintLines(bg, freeItemsToPaint);
    414426                        }
    415427
    416428                        if (isActualFrame /* && toPaint == DisplayIO.getCurrentFrame() */)
    417                                 PaintNonLinesNonPicture(bg, Frame.FreeItems);
     429                                PaintNonLinesNonPicture(bg, freeItemsToPaint);
    418430
    419431                        // BROOK: Ensure popups are repainted
     
    465477        }
    466478
    467         private static void Paint(Image left, Image right, Color background) {
    468                 if (_MessageBuffer == null) {
    469                         GraphicsEnvironment ge = GraphicsEnvironment
    470                                         .getLocalGraphicsEnvironment();
    471                         _MessageBuffer = ge.getDefaultScreenDevice()
    472                                         .getDefaultConfiguration().createCompatibleVolatileImage(
    473                                                         _MaxSize.width,
    474                                                         (isAudienceMode() ? 0 : MESSAGE_BUFFER_HEIGHT));
    475                 }
    476 
    477                 paintMessage(_MessageBuffer.createGraphics(), background);
    478                 Graphics g = _DisplayGraphics.create();
     479        private static void Paint(Graphics g, Image left, Image right, Color background) {
    479480
    480481                // if TwinFrames mode is on, then clipping etc has to be set
     
    503504                                g.drawImage(right, 0, 0, Item.DEFAULT_BACKGROUND, null);
    504505                }
    505                 // Dont display the message area in audience mode
    506                 if (!isAudienceMode()) {
    507                         // draw the message area
    508                         g.drawImage(_MessageBuffer, 0, _MaxSize.height, null);
    509                 }
    510                 g.dispose();
    511 
    512         }
    513 
    514         /**
    515          * Paints the message area
    516          *
    517          * @param g
    518          * @param background
    519          */
    520         private static void paintMessage(Graphics2D g, Color background) {
    521                 ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
    522                                 RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    523                 g.setColor(background);
    524                 g.fillRect(0, 0, _MaxSize.width, MESSAGE_BUFFER_HEIGHT);
    525                 g.setFont(_MessageFont);
    526                 g.setColor(Color.BLACK);
    527                 g.drawLine(0, 0, _MaxSize.width, 0);
    528                 for (Item t : Messages)
    529                         PaintItem(g, t);
    530                 if (MessageLink.getLink() != null)
    531                         PaintItem(g, MessageLink);
    532                 g.dispose();
     506
    533507        }
    534508
     
    539513                g.dispose();
    540514        }
    541 
    542         /**
    543          * Called to refresh the display screen.
    544          *
    545          */
    546         public static void Repaint() {
    547                 Runtime.getRuntime();
    548                 if (_DisplayGraphics == null)
    549                         return;
    550 
    551                 if (UserSettings.Threading) {
    552                         if (painter == null) {
    553                                 painter = new FrameGraphics().new Repainter();
    554 
    555                                 painter.setDaemon(true);
    556                                 painter.setPriority(Thread.MIN_PRIORITY);
    557 
    558                                 painter.start();
    559                         } else
    560                                 painter.run();
    561                 } else {
    562                         Frame[] toPaint = DisplayIO.getFrames();
    563 
    564                         if (toPaint != null) {
    565                                 Image left = Paint(toPaint[0]);
    566                                 Image right = Paint(toPaint[1]);
    567                                 Paint(left, right, Item.DEFAULT_BACKGROUND);
    568                         }
    569                 }
    570         }
    571 
    572         private static Repainter painter = null;
    573515
    574516        private static void PaintNonLinesNonPicture(Graphics2D g, List<Item> toPaint) {
     
    601543        }
    602544
     545
    603546        /**
    604547         * Paint filled areas and their surrounding lines as well as pictures.
    605          *
     548         * Note: floating widgets are painted as fills
    606549         * @param g
    607550         * @param toPaint
    608551         */
    609         private static void PaintPictures(Graphics2D g, List<Item> toPaint) {
    610                 // Use this set to keep track of the items that dont need to be
    611                 // repainted
    612                 Collection<Item> done = new HashSet<Item>();
     552        private static void PaintPictures(Graphics2D g, List<Item> toPaint,
     553                        HashSet<Item> fillOnlyItems, HashSet<Item> done) {
     554               
    613555                List<Item> toFill = new LinkedList<Item>();
    614556                for (Item i : toPaint) {
     
    634576                        }
    635577                }
     578               
     579                if (fillOnlyItems != null) {
     580                        for (Item i : fillOnlyItems) {
     581                                if (done.contains(i)) continue;
     582                                else if (!isAudienceMode() || !i.isConnectedToAnnotation()) {
     583                                        toFill.add(i);
     584                                }
     585                                done.addAll(i.getAllConnected());
     586                        }
     587                }
     588               
    636589                // Sort the items to fill
    637590                Collections.sort(toFill, new Comparator<Item>() {
     
    639592                                Double aArea = a.getEnclosedArea();
    640593                                Double bArea = b.getEnclosedArea();
    641                                 return aArea.compareTo(bArea) * -1;
     594                                int cmp = aArea.compareTo(bArea);
     595                                if (cmp == 0) {
     596                                        return new Integer(a.getID()).compareTo(b.getID());
     597                                }
     598                                return cmp * -1;
    642599                        }
    643600                });
     
    715672                // Mike: TODO comment on why the line below is used!!
    716673                // I forgot already!!Opps
    717                 boolean freeItem = Frame.FreeItems.contains(item);
     674                boolean freeItem = FreeItems.getInstance().contains(item);
    718675                for (Item i : item.getAllConnected()) {
    719                         if (/* freeItem || */!Frame.FreeItems.contains(i)) {
     676                        if (/* freeItem || */!FreeItems.getInstance().contains(i)) {
    720677                                i.setHighlightMode(connectedNewMode);
    721678                        }
     
    723680                if (!freeItem && newMode != connectedNewMode)
    724681                        item.setHighlightMode(newMode);
    725                 Repaint();
    726         }
    727 
    728         public static void OverwriteMessage(String message) {
    729                 for (int ind = Messages.length - 1; ind >= 0; ind--) {
    730                         if (Messages[ind] != null) {
    731                                 Messages[ind].setText(getMessagePrefix(false) + message);
    732                                 Repaint();
    733                                 return;
    734                         }
    735                 }
    736 
    737                 // if we have not returned, then there are no messages yet
    738                 DisplayMessage(message, Color.darkGray);
    739         }
    740 
    741         /**
    742          * Displays the given message in the message area of the Frame, any previous
    743          * message is cleared from the screen.
    744          *
    745          * @param message
    746          *            The message to display to the user in the message area
    747          */
    748         public static void DisplayMessage(String message) {
    749                 DisplayMessageAlways(message);
    750         }
    751 
    752         public static void DisplayMessageOnce(String message) {
    753                 displayMessage(message, null, null, Color.BLACK, false);
    754         }
    755 
    756         public static void DisplayMessage(String message, Color textColor) {
    757                 displayMessage(message, null, null, textColor);
    758                 // Misc.Beep();
    759         }
    760 
    761         public static void DisplayMessage(Text message) {
    762                 displayMessage(message.getFirstLine(), message.getLink(), message
    763                                 .getAction(), message.getColor());
    764                 // Misc.Beep();
    765         }
    766 
    767         public static void DisplayMessageAlways(String message) {
    768                 displayMessage(message, null, null, Color.BLACK);
    769                 // Misc.Beep();
    770         }
    771 
    772         public static void WarningMessage(String message) {
    773                 displayMessage(message, null, null, Color.MAGENTA);
    774                 // Misc.Beep();
    775         }
    776 
    777         private static String _lastMessage = null;
    778 
    779         private static void displayMessage(String message, String link,
    780                         List<String> actions, Color color) {
    781                 displayMessage(message, link, actions, color, true);
    782         }
    783 
    784         private static void displayMessage(String message, String link,
    785                         List<String> actions, Color color, boolean displayAlways) {
    786 
    787                 System.out.println(message);
    788                 assert (message != null);
    789 
    790                 if (_SupressMessages)
    791                         return;
    792 
    793                 if (!displayAlways && message.equals(_lastMessage)) {
    794                         Misc.Beep();
    795                         return;
    796                 }
    797                 _lastMessage = message;
    798 
    799                 if (_creator == null) {
    800                         _creator = new FrameCreator(MESSAGES_FRAMESET_NAME, true);
    801 
    802                         // set up 'Messages' link on the right hand side
    803                         MessageLink.setPosition(_MaxSize.width - MESSAGE_LINK_Y_OFFSET,
    804                                         MESSAGE_LINK_X);
    805                         MessageLink.setOffset(0, -_MaxSize.height);
    806                 }
    807 
    808                 // if the message slots have not all been used yet
    809                 if (_MessageCount <= Messages.length) {
    810                         int pos = 15;
    811                         // find the next empty slot, and create the new message
    812                         for (int i = 0; i < Messages.length; i++) {
    813                                 if (Messages[i] == null) {
    814                                         Messages[i] = new Text(getMessagePrefix(true) + message);
    815                                         Messages[i].setPosition(20, pos);
    816                                         Messages[i].setOffset(0, -_MaxSize.height);
    817                                         Messages[i].setMaxSize(_MaxSize);
    818                                         Messages[i].setColor(color);
    819                                         Messages[i].setLink(link);
    820                                         _creator.addItem(Messages[i].copy());
    821                                         MessageLink.setLink(_creator.getCurrent());
    822                                         Repaint();
    823                                         return;
    824                                 }
    825 
    826                                 pos += 25;
    827                         }
    828                 }
    829 
    830                 // if we have not returned then all message slots are used
    831                 for (int i = 0; i < Messages.length - 1; i++) {
    832                         Messages[i].setText(Messages[i + 1].getFirstLine());
    833                         Messages[i].setColor(Messages[i + 1].getColor());
    834                         Messages[i].setLink(Messages[i + 1].getLink());
    835                 }
    836 
    837                 // show the new message
    838                 Text last = Messages[Messages.length - 1];
    839                 last.setColor(color);
    840                 // Make set the text for the new message
    841                 last.setText(getMessagePrefix(true) + message);
    842                 last.setLink(link);
    843                 last.setActions(actions);
    844 
    845                 _creator.addItem(last.copy());
    846                 // update the link to the latest message frame
    847                 MessageLink.setLink(_creator.getCurrent());
    848                 Repaint();
    849         }
    850 
    851         private static String getMessagePrefix(boolean incrementCounter) {
    852                 if (incrementCounter)
    853                         _MessageCount++;
    854                 return "@" + _MessageCount + ": ";
    855         }
    856 
    857         /**
    858          * Checks if the error message ends with a frame name after the
    859          * frameNameSeparator symbol
    860          *
    861          * @param message
    862          *            the message to be displayed
    863          */
    864         public static void LinkedErrorMessage(String message) {
    865                 if (_SupressMessages)
    866                         return;
    867                 Misc.Beep();
    868                 String[] tokens = message.split(Text.FRAME_NAME_SEPARATOR);
    869                 String link = null;
    870                 if (tokens.length > 1)
    871                         link = tokens[tokens.length - 1];
    872                 displayMessage(message, link, null, ERROR_COLOR);
    873         }
    874 
    875         public static void ErrorMessage(String message) {
    876                 if (_SupressMessages)
    877                         return;
    878                 Misc.Beep();
    879                 displayMessage(message, null, null, ERROR_COLOR);
    880         }
    881 
    882         private class Repainter extends Thread {
    883                 public boolean isPainting = false;
    884 
    885                 public void run() {
    886                         // TODO see if there is any other way to deal with this
    887                         if (_MaxSize.width <= 0 || _MaxSize.height <= 0) {
    888                                 return;
    889                         }
    890                         isPainting = true;
    891 
    892                         Frame[] toPaint = DisplayIO.getFrames();
    893 
    894                         if (toPaint != null) {
    895                                 Image left = Paint(toPaint[0]);
    896                                 Image right = Paint(toPaint[1]);
    897                                 Paint(left, right, Item.DEFAULT_BACKGROUND);
    898                         }
    899                         isPainting = false;
    900                 }
    901         }
    902 
    903         /**
    904          * Invalidates the buffered image of the current Frame and forces it to be
    905          * repainted on to the screen.
    906          */
    907         public static void ForceRepaint() {
    908                 Frame current = DisplayIO.getCurrentFrame();
    909 
    910                 if (current == null)
    911                         return;
    912 
    913682                Repaint();
    914683        }
     
    925694                        return;
    926695
    927                 Image vi = Paint(toUpdate, paintOverlays);
     696                Image vi = Paint(toUpdate, null, paintOverlays);
    928697                toUpdate.setBuffer(vi);
    929         }
    930 
    931         public static void SupressMessages(boolean val) {
    932                 _SupressMessages = val;
    933698        }
    934699
     
    939704                                                Browser._theBrowser.getContentPane());
    940705
     706                                c.setIgnoreRepaint(true);
     707                                ((JComponent)c).setDoubleBuffered(false);
    941708                                g.translate(p.x, p.y);
    942709                                c.paint(g);
     
    952719                return _Mode;
    953720        }
     721
     722        // Damaged areas pending to render. Accessessed by multiple threads
     723        private static HashSet<Rectangle> damagedAreas = new HashSet<Rectangle>();
     724       
     725        /**
     726         * Checks that the item is visible (on current frame && overlays) - if visible
     727         * then damaged area will be re-rendered on the next refresh.
     728         * @param damagedItem
     729         * @param toRepaint
     730         */
     731        public static void invalidateItem(Item damagedItem, Rectangle toRepaint) {
     732                // Only add area to repaint if item is visible...
     733                if (ItemUtils.isVisible(damagedItem)) {
     734                        synchronized(damagedAreas) {
     735                                damagedAreas.add(toRepaint);
     736                        }
     737                } else if(MessageBay.isMessageItem(damagedItem)) {
     738                        MessageBay.addDirtyArea(toRepaint);
     739                }
     740        }
     741       
     742        /**
     743         * The given area will be re-rendered in the next refresh. This is the quicker version
     744         * and is more useful for re-rendering animated areas.
     745         * @param toRepaint
     746         */
     747        public static void invalidateArea(Rectangle toRepaint) {
     748                synchronized(damagedAreas) {
     749                        damagedAreas.add(toRepaint);
     750                }
     751        }
     752       
     753        public static void clearInvalidAreas() {
     754                synchronized(damagedAreas) {
     755                        damagedAreas.clear();
     756                }
     757        }
     758       
     759        /**
     760         * Invalidates the buffered image of the current Frame and forces it to be
     761         * repainted on to the screen. Repaints all items. This is more expensive
     762         * than refresh.
     763         */
     764        public static void ForceRepaint() {  // TODO: TEMP: Use refresh
     765                Frame current = DisplayIO.getCurrentFrame();
     766
     767                if (current == null)
     768                        return;
     769                refresh(false);
     770        }
     771       
     772        public static void Repaint() { // TODO: TEMP: Use refresh
     773                refresh(true);
     774        }
     775
     776        /**
     777         * Called to refresh the display screen. Thread safe.
     778         */
     779        public static void refresh(boolean useInvalidation) {
     780               
     781                if (_DisplayGraphics == null) return;
     782
     783                Area clip = null;
     784                if (useInvalidation) { // build clip
     785                       
     786                        synchronized(damagedAreas) {
     787                                if (!damagedAreas.isEmpty()) {
     788                                       
     789                                        for (Rectangle r : damagedAreas) {
     790                                                if (clip == null) clip = new Area(r);
     791                                                clip.add(new Area(r)); 
     792                                        }
     793                                        damagedAreas.clear();
     794                                } else return; // nothing to render
     795                        }
     796               
     797                } else {
     798                        synchronized(damagedAreas) {
     799                                damagedAreas.clear();
     800                        }
     801                        System.out.println("FULLSCREEN REFRESH"); // TODO: REMOVE
     802                }
     803
     804                Frame[] toPaint = DisplayIO.getFrames();
     805                Image left = Paint(toPaint[0], clip);
     806                Image right = Paint(toPaint[1], clip);
     807               
     808                Graphics dg = _DisplayGraphics.create();
     809               
     810                // Paint frame to window
     811                Paint(dg, left, right, Item.DEFAULT_BACKGROUND);
     812               
     813                // Paint message bay
     814                MessageBay.refresh(useInvalidation, dg, Item.DEFAULT_BACKGROUND);
     815               
     816                dg.dispose();
     817        }
     818       
     819        /**
     820         * If wanting to refresh from another thread - other than the main thread that
     821         * handles the expeditee datamodel (modifying / accessing / rendering). Use
     822         * this method for thread safety.
     823         */
     824        public static synchronized void requestRefresh(boolean useInvalidation) {
     825               
     826                _requestMarsheller._useInvalidation = useInvalidation;
     827               
     828                if (_requestMarsheller._isQueued) {
     829                        return;
     830                }
     831               
     832                _requestMarsheller._isQueued = true;
     833                EventQueue.invokeLater(_requestMarsheller); // Render on AWT thread
     834        }
     835       
     836        private static RenderRequestMarsheller _requestMarsheller = new FrameGraphics().new RenderRequestMarsheller();
     837       
     838        /**
     839         * Used for marshelling render requests from foreign threads to the event dispatcher thread... (AWT)
     840         * @author Brook Novak
     841         */
     842        private class RenderRequestMarsheller implements Runnable {
     843
     844                boolean _useInvalidation = true;
     845                boolean _isQueued = false;
     846               
     847                public void run() {
     848                        refresh(_useInvalidation);
     849                        _isQueued = false;
     850                        _useInvalidation = true;
     851                }
     852
     853        }
     854       
    954855}
Note: See TracChangeset for help on using the changeset viewer.