EMMA Coverage Report (generated Sun Apr 20 22:38:01 CEST 2008)
[all classes][net.sf.jomic.ui]

COVERAGE SUMMARY FOR SOURCE FILE [FullScreenViewer.java]

nameclass, %method, %block, %line, %
FullScreenViewer.java33%  (2/6)51%  (18/35)59%  (667/1134)60%  (163.9/275)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class FullScreenViewer$10%   (0/1)100% (0/0)100% (0/0)100% (0/0)
     
class FullScreenViewer$CancelFullScreenRunner0%   (0/1)0%   (0/2)0%   (0/26)0%   (0/8)
FullScreenViewer$CancelFullScreenRunner (FullScreenViewer): void 0%   (0/1)0%   (0/10)0%   (0/3)
run (): void 0%   (0/1)0%   (0/16)0%   (0/5)
     
class FullScreenViewer$DelegateActionToControllerRunner0%   (0/1)0%   (0/2)0%   (0/16)0%   (0/6)
FullScreenViewer$DelegateActionToControllerRunner (FullScreenViewer, ActionEv... 0%   (0/1)0%   (0/9)0%   (0/4)
run (): void 0%   (0/1)0%   (0/7)0%   (0/2)
     
class FullScreenViewer$ShowErrorRunner0%   (0/1)0%   (0/2)0%   (0/21)0%   (0/7)
FullScreenViewer$ShowErrorRunner (FullScreenViewer, ActionEvent, Throwable): ... 0%   (0/1)0%   (0/12)0%   (0/5)
run (): void 0%   (0/1)0%   (0/9)0%   (0/2)
     
class FullScreenViewer100% (1/1)59%  (16/27)62%  (657/1061)64%  (158.9/249)
actionPerformed (ActionEvent): void 0%   (0/1)0%   (0/139)0%   (0/32)
keyPressed (KeyEvent): void 0%   (0/1)0%   (0/46)0%   (0/9)
keyReleased (KeyEvent): void 0%   (0/1)0%   (0/1)0%   (0/1)
keyTyped (KeyEvent): void 0%   (0/1)0%   (0/1)0%   (0/1)
mouseClicked (MouseEvent): void 0%   (0/1)0%   (0/1)0%   (0/1)
mouseExited (MouseEvent): void 0%   (0/1)0%   (0/1)0%   (0/1)
mousePressed (MouseEvent): void 0%   (0/1)0%   (0/1)0%   (0/1)
mouseReleased (MouseEvent): void 0%   (0/1)0%   (0/51)0%   (0/13)
performCancel (): void 0%   (0/1)0%   (0/7)0%   (0/2)
performCancelAndWait (): void 0%   (0/1)0%   (0/7)0%   (0/2)
propertyChange (PropertyChangeEvent): void 0%   (0/1)0%   (0/19)0%   (0/6)
setUpDefaultDevice (): void 100% (1/1)65%  (79/122)62%  (13/21)
setVisibleTrue (): void 100% (1/1)67%  (93/138)81%  (24.2/30)
dispose (): void 100% (1/1)70%  (19/27)78%  (7/9)
<static initializer> 100% (1/1)80%  (12/15)80%  (0.8/1)
refreshDisplay (): void 100% (1/1)80%  (104/130)84%  (25.9/31)
FullScreenViewer (): void 100% (1/1)96%  (112/117)100% (23/23)
addShortCutKey (KeyStroke, String): void 100% (1/1)100% (13/13)100% (3/3)
assignShortCutKeys (): void 100% (1/1)100% (83/83)100% (18/18)
instance (): FullScreenViewer 100% (1/1)100% (8/8)100% (3/3)
invokeLaterRefreshComicView (): void 100% (1/1)100% (6/6)100% (2/2)
isVisible (): boolean 100% (1/1)100% (3/3)100% (1/1)
mouseEntered (MouseEvent): void 100% (1/1)100% (1/1)100% (1/1)
setController (JomicFrame): void 100% (1/1)100% (23/23)100% (8/8)
setUpComicView (): void 100% (1/1)100% (26/26)100% (5/5)
setVisible (boolean): void 100% (1/1)100% (16/16)100% (7/7)
setVisibleFalse (): void 100% (1/1)100% (59/59)100% (17/17)
     
class FullScreenViewer$RefreshDisplayRunner100% (1/1)100% (2/2)100% (10/10)100% (5/5)
FullScreenViewer$RefreshDisplayRunner (FullScreenViewer): void 100% (1/1)100% (6/6)100% (3/3)
run (): void 100% (1/1)100% (4/4)100% (2/2)

1// Jomic - a viewer for comic book archives.
2// Copyright (C) 2004-2008 Thomas Aglassinger
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program.  If not, see <http://www.gnu.org/licenses/>.
16package net.sf.jomic.ui;
17 
18import java.awt.DisplayMode;
19import java.awt.Graphics2D;
20import java.awt.GraphicsDevice;
21import java.awt.GraphicsEnvironment;
22import java.awt.event.ActionEvent;
23import java.awt.event.ActionListener;
24import java.awt.event.InputEvent;
25import java.awt.event.KeyEvent;
26import java.awt.event.KeyListener;
27import java.awt.event.MouseEvent;
28import java.awt.event.MouseListener;
29import java.awt.image.BufferStrategy;
30import java.awt.image.RenderedImage;
31import java.beans.PropertyChangeEvent;
32import java.beans.PropertyChangeListener;
33import java.lang.reflect.InvocationTargetException;
34import java.util.HashMap;
35import java.util.Map;
36import java.util.TreeMap;
37 
38import javax.swing.JFrame;
39import javax.swing.JMenu;
40import javax.swing.JMenuItem;
41import javax.swing.KeyStroke;
42import javax.swing.SwingUtilities;
43 
44import net.sf.jomic.comic.ComicModel;
45import net.sf.jomic.comic.ComicSheet;
46import net.sf.jomic.comic.ComicSheetLayout;
47import net.sf.jomic.comic.ComicView;
48import net.sf.jomic.common.ComicSheetRenderSettings;
49import net.sf.jomic.common.FullScreenCancelabel;
50import net.sf.jomic.common.JomicTools;
51import net.sf.jomic.common.PropertyConstants;
52import net.sf.jomic.common.Settings;
53import net.sf.jomic.tools.ImageTools;
54import net.sf.jomic.tools.LocaleTools;
55import net.sf.wraplog.Logger;
56 
57/**
58 *  Comic viewer in full screen mode connected to a JomicFrame.
59 *
60 * @author    Thomas Aglassinger
61 * @see       JomicFrame
62 */
63public final class FullScreenViewer
64    implements ActionListener, FullScreenCancelabel, KeyListener, PropertyChangeListener, MouseListener
65{
66    private static final String DELEGATE_TO_CONTROLLER = "delegateToController;";
67    private static final String REFRESH_VIEW = "refreshView;";
68    private static final String REMAIN_IN_FULL_SCREEN = "remainInFullScreen;";
69    private static final int WINDOW_HEIGHT = 500;
70    private static final int WINDOW_WIDTH = 600;
71 
72    private static /*@ spec_public nullable @*/ FullScreenViewer instance;
73 
74    //@ public ghost boolean disposed;
75 
76    private /*@ nullable @*/ ComicModel comic;
77    private /*@ nullable @*/ ComicView comicView;
78    private Map commandHandlingMap;
79    private /*@ nullable @*/ GraphicsDevice defaultDevice;
80    private /*@ nullable @*/ JFrame frame;
81    private ImageTools imageTools;
82    private boolean isVisible;
83    private JomicTools jomicTools;
84    private boolean /*@ spec_public */ actionListenersAdded;
85    private LocaleTools localeTools;
86    private Logger logger;
87    private /*@ nullable @*/ DisplayMode oldDisplayMode;
88    private /*@ nullable @*/ JomicFrame controller;
89    private Settings settings;
90    private boolean /*@ spec_public */ settingsChangedListenerAdded;
91    private boolean showFullScreenInWindow;
92    private Map keyStrokeToCommandMap;
93    private boolean ignoreNextLeftMouseButtonReleased;
94 
95    /**
96     *  Create a new fullscreen viewer for the specified controlling JomicFrame. The full screen viewer
97     *  opens in a borderless frame processes some commands such as page navigation. All other
98     *  commands revert to window mode, and delegate the command to the <code>controller</code>.
99     *
100     * @param  newController  the JomicFrame acting as controller for this full screen viewer
101     */
102    private FullScreenViewer() {
103        logger = Logger.getLogger(FullScreenViewer.class);
104        imageTools = ImageTools.instance();
105        jomicTools = JomicTools.instance();
106        localeTools = LocaleTools.instance();
107        settings = Settings.instance();
108        comicView = new ComicView();
109        comicView.setBorder(null);
110        keyStrokeToCommandMap = new HashMap();
111        commandHandlingMap = new TreeMap();
112        commandHandlingMap.put(Commands.ADVANCE, DELEGATE_TO_CONTROLLER + REFRESH_VIEW + REMAIN_IN_FULL_SCREEN);
113        commandHandlingMap.put(Commands.FIRST_PAGE, DELEGATE_TO_CONTROLLER + REFRESH_VIEW + REMAIN_IN_FULL_SCREEN);
114        commandHandlingMap.put(Commands.GO_NEXT, DELEGATE_TO_CONTROLLER + REFRESH_VIEW + REMAIN_IN_FULL_SCREEN);
115        commandHandlingMap.put(Commands.GO_NEXT_FEW, DELEGATE_TO_CONTROLLER + REFRESH_VIEW + REMAIN_IN_FULL_SCREEN);
116        commandHandlingMap.put(Commands.GO_PREVIOUS, DELEGATE_TO_CONTROLLER + REFRESH_VIEW + REMAIN_IN_FULL_SCREEN);
117        commandHandlingMap.put(Commands.GO_PREVIOUS_FEW, DELEGATE_TO_CONTROLLER + REFRESH_VIEW + REMAIN_IN_FULL_SCREEN);
118        commandHandlingMap.put(Commands.LAST_PAGE, DELEGATE_TO_CONTROLLER + REFRESH_VIEW + REMAIN_IN_FULL_SCREEN);
119        commandHandlingMap.put(Commands.FULL_SCREEN, "");
120        commandHandlingMap.put(Commands.RETREAT, DELEGATE_TO_CONTROLLER + REFRESH_VIEW + REMAIN_IN_FULL_SCREEN);
121        commandHandlingMap.put(Commands.ROTATE_LEFT, DELEGATE_TO_CONTROLLER + REFRESH_VIEW + REMAIN_IN_FULL_SCREEN);
122        commandHandlingMap.put(Commands.ROTATE_RIGHT, DELEGATE_TO_CONTROLLER + REFRESH_VIEW + REMAIN_IN_FULL_SCREEN);
123        commandHandlingMap.put(Commands.TOGGLE_SWAP_LEFT_AND_RIGHT_IMAGE,
124                DELEGATE_TO_CONTROLLER + REFRESH_VIEW + REMAIN_IN_FULL_SCREEN);
125    }
126 
127    //@ ensures instance != null;
128    public static synchronized FullScreenViewer instance() {
129        if (instance == null) {
130            instance = new FullScreenViewer();
131        }
132        return instance;
133    }
134 
135    public void setController(/*@ nullable @*/ JomicFrame newController) {
136        if (newController != null) {
137            controller = newController;
138            comic = controller.getComicModel();
139            assignShortCutKeys();
140        } else {
141            controller = null;
142            comic = null;
143            keyStrokeToCommandMap.clear();
144        }
145    }
146 
147    //@ ensures isVisible() == newVisible;
148    public void setVisible(boolean newVisible) {
149        if (newVisible) {
150            setVisibleTrue();
151            isVisible = true;
152            invokeLaterRefreshComicView();
153        } else {
154            setVisibleFalse();
155            isVisible = false;
156        }
157    }
158 
159    public /*@ pure @*/ boolean isVisible() {
160        return isVisible;
161    }
162 
163    //@ ensures actionListenersAdded
164    //@ ensures settingsChangedListenerAdded
165    private void setVisibleTrue() {
166        assert controller != null;
167 
168        setUpDefaultDevice();
169        setUpComicView();
170 
171        // Try to switch to full screen, and browse comic.
172        boolean viewerIsVisible = false;
173 
174        showFullScreenInWindow = settings.getBooleanProperty(PropertyConstants.TEST_SHOW_FULL_SCREEN_IN_WINDOW);
175        if (showFullScreenInWindow) {
176            frame = new JFrame();
177            frame.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
178        } else {
179            frame = new JFrame(defaultDevice.getDefaultConfiguration());
180        }
181        try {
182            controller.setVisible(false);
183            frame.setIgnoreRepaint(true);
184            if (!showFullScreenInWindow) {
185                frame.setUndecorated(true);
186                defaultDevice.setFullScreenWindow(frame);
187            }
188            frame.setTitle(FullScreenViewer.class.getName());
189            frame.setResizable(false);
190            frame.validate();
191            if (showFullScreenInWindow) {
192                frame.setVisible(true);
193            } else {
194                frame.createBufferStrategy(2);
195            }
196            frame.addKeyListener(instance());
197            frame.addMouseListener(instance());
198            actionListenersAdded = true;
199            settings.addPropertyChangeListener(PropertyConstants.MOST_RECENT_PAGE, this);
200            settingsChangedListenerAdded = true;
201            viewerIsVisible = true;
202        } finally {
203            if (!viewerIsVisible) {
204                setVisible(false);
205                controller.setVisible(true);
206            }
207        }
208    }
209 
210    //@ ensures comicView != null;
211    private /*@ helper @*/ void setUpComicView() {
212        comicView.setModel(comic, null, settings.getMostRecentPage());
213        comicView.setTwoPageMode(settings.getTwoPageMode());
214        comicView.setSwapLeftAndRightImage(settings.getSwapLeftAndRightImage());
215        comicView.setScaleMode(ImageTools.SCALE_FIT);
216    }
217 
218    //@ ensures defaultDevice != null;
219    //@ ensures oldDisplayMode != null;
220    //@ signals_only IllegalStateException;
221    private /*@ helper @*/ void setUpDefaultDevice() {
222        GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
223 
224        if (env == null) {
225            String errorMessage = localeTools.getMessage("errors.cannotObtainGraphicsEnvirontment");
226 
227            throw new IllegalStateException(errorMessage);
228        }
229 
230        GraphicsDevice[] devices = env.getScreenDevices();
231 
232        if (devices == null) {
233            String errorMessage = localeTools.getMessage("errors.cannotObtainScreenDevices");
234 
235            throw new IllegalStateException(errorMessage);
236        }
237        if (devices.length == 0) {
238            String errorMessage = localeTools.getMessage("errors.listOfScreenDevicesMustNotBeEmpty");
239 
240            throw new IllegalStateException(errorMessage);
241        }
242        defaultDevice = devices[0];
243        oldDisplayMode = defaultDevice.getDisplayMode();
244        if (logger.isInfoEnabled()) {
245            logger.info("graphics device=\"" + defaultDevice.getIDstring()
246                    + "\"");
247            logger.info("display mode=" + oldDisplayMode.getWidth() + "x"
248                    + oldDisplayMode.getHeight() + "x"
249                    + oldDisplayMode.getBitDepth() + " @ "
250                    + oldDisplayMode.getRefreshRate());
251        }
252        boolean isFullScreen = defaultDevice.isFullScreenSupported();
253 
254        if (!isFullScreen) {
255            String errorMessage = localeTools.getMessage(
256                    "errors.deviceMustSupportFullScreen", defaultDevice.getIDstring());
257 
258            throw new IllegalStateException(errorMessage);
259        }
260    }
261 
262    /**
263     *  Delegate all events to controller, but also process some yourself (for example navigational
264     *  commands). Unless the command is in COMMANDS_REMAINING_IN_FULL_SCREEN, revert back to window
265     *  mode.
266     */
267    //@ also
268    //@     requires event.getActionCommand() != null;
269    public void actionPerformed(ActionEvent event) {
270        try {
271            String command = event.getActionCommand();
272            String commandActions = (String) commandHandlingMap.get(command);
273            boolean delegateToController;
274            boolean refreshView;
275            boolean remainInFullScreen;
276 
277            logger.info("command={}: commandActions={}", command, commandActions);
278            if (commandActions != null) {
279                delegateToController = commandActions.indexOf(DELEGATE_TO_CONTROLLER) >= 0;
280                refreshView = commandActions.indexOf(REFRESH_VIEW) >= 0;
281                remainInFullScreen = commandActions.indexOf(REMAIN_IN_FULL_SCREEN) >= 0;
282                
283                // In case advance/retreat have to open a new file, exit full screen.
284                if (remainInFullScreen) {
285                    if (command.equals(Commands.ADVANCE) && comicView.isLast()) {
286                        remainInFullScreen = false;
287                    } else if (command.equals(Commands.RETREAT) && comicView.isFirst()) {
288                        remainInFullScreen = false;
289                    }
290                }
291            } else {
292                // Command cannot be processed in full screen.
293                delegateToController = true;
294                refreshView = false;
295                remainInFullScreen = false;
296            }
297            if (logger.isDebugEnabled()) {
298                logger.debug("command=" + command
299                        + ", delegateToController=" + delegateToController
300                        + ", refreshView=" + refreshView
301                        + ", remainInFullScreen=" + remainInFullScreen);
302            }
303 
304            if (!remainInFullScreen) {
305                performCancel();
306            }
307            if (delegateToController) {
308                final ActionEvent eventToDelegate = event;
309 
310                logger.debug("delegate command to controller: {}", command);
311                SwingUtilities.invokeLater(new DelegateActionToControllerRunner(eventToDelegate));
312            }
313            if (refreshView) {
314                invokeLaterRefreshComicView();
315            }
316        } catch (Throwable error) {
317            final ActionEvent eventToReport = event;
318            final Throwable stackToReport = error;
319 
320            performCancel();
321            SwingUtilities.invokeLater(new ShowErrorRunner(eventToReport, stackToReport));
322        }
323    }
324 
325    //@ ensures !actionListenersAdded
326    //@ ensures !settingsChangedListenerAdded
327    private void setVisibleFalse() {
328        if (actionListenersAdded) {
329            frame.removeMouseListener(this);
330            frame.removeKeyListener(this);
331            actionListenersAdded = false;
332        }
333        if (settingsChangedListenerAdded) {
334            settings.removePropertyChangeListener(PropertyConstants.MOST_RECENT_PAGE, this);
335            settingsChangedListenerAdded = false;
336        }
337        if (controller != null) {
338            controller.getComicView().setImageIndex(comicView.getImageIndex());
339        }
340        if (defaultDevice != null) {
341            defaultDevice.setFullScreenWindow(null);
342            defaultDevice = null;
343        }
344        if (frame != null) {
345            frame.removeKeyListener(this);
346            frame.dispose();
347            frame = null;
348        }
349    }
350 
351    //@ requires !disposed;
352    //@ ensures !isVisible();
353    //@ ensures disposed;
354    public void dispose() {
355        if (isVisible()) {
356            setVisible(false);
357        }
358        //@ set disposed = true;
359        if (comicView != null) {
360            comicView.dispose();
361            comicView = null;
362        }
363        setController(null);
364        if (settingsChangedListenerAdded) {
365            settings.removePropertyChangeListener(PropertyConstants.MOST_RECENT_PAGE, this);
366        }
367    }
368 
369    //@ also
370    //@     requires event.getPropertyName().equals(PropertyConstants.MOST_RECENT_PAGE);
371    public void propertyChange(PropertyChangeEvent event) {
372        String newPageText = (String) event.getNewValue();
373        int newPage = Integer.parseInt(newPageText);
374 
375        logger.info("change page to {}", newPageText);
376        comicView.setPage(newPage);
377        invokeLaterRefreshComicView();
378    }
379 
380    private void addShortCutKey(KeyStroke keyStroke, String command) {
381        logger.debug("assign KeyStroke \"{}\" to command \"{}\" ", keyStroke, command);
382        keyStrokeToCommandMap.put(keyStroke, command);
383    }
384 
385    private void assignShortCutKeys() {
386        // Copy short cuts from menu.
387        for (int menuIndex = 0; menuIndex < controller.getJMenuBar().getMenuCount(); menuIndex += 1) {
388            JMenu menuToScanForItems = controller.getJMenuBar().getMenu(menuIndex);
389 
390            for (int menuItemIndex = 0; menuItemIndex < menuToScanForItems.getItemCount(); menuItemIndex += 1) {
391                JMenuItem itemToAnalyseForKeyStroke = menuToScanForItems.getItem(menuItemIndex);
392 
393                if (itemToAnalyseForKeyStroke != null) {
394                    KeyStroke itemStroke = itemToAnalyseForKeyStroke.getAccelerator();
395 
396                    if (itemStroke != null) {
397                        String itemCommand = itemToAnalyseForKeyStroke.getActionCommand();
398 
399                        addShortCutKey(itemStroke, itemCommand);
400                    }
401                }
402            }
403        }
404 
405        // Add additional, non-menu shortcuts. TODO: Consolidate with JomicFrame.
406        addShortCutKey(KeyStroke.getKeyStroke("END"), Commands.LAST_PAGE);
407        addShortCutKey(KeyStroke.getKeyStroke("HOME"), Commands.FIRST_PAGE);
408        addShortCutKey(KeyStroke.getKeyStroke("PAGE_DOWN"), Commands.GO_NEXT);
409        addShortCutKey(KeyStroke.getKeyStroke("PAGE_UP"), Commands.GO_PREVIOUS);
410        addShortCutKey(KeyStroke.getKeyStroke("alt PAGE_DOWN"), Commands.GO_NEXT_FEW);
411        addShortCutKey(KeyStroke.getKeyStroke("alt PAGE_UP"), Commands.GO_PREVIOUS_FEW);
412        addShortCutKey(KeyStroke.getKeyStroke("SPACE"), Commands.ADVANCE);
413        addShortCutKey(KeyStroke.getKeyStroke("ESCAPE"), Commands.FULL_SCREEN);
414    }
415 
416    private void invokeLaterRefreshComicView() {
417        SwingUtilities.invokeLater(new RefreshDisplayRunner());
418    }
419 
420    public void performCancel() {
421        SwingUtilities.invokeLater(new CancelFullScreenRunner());
422    }
423 
424    //@ ensures !isVisible();
425    public void performCancelAndWait() throws InterruptedException, InvocationTargetException {
426        SwingUtilities.invokeAndWait(new CancelFullScreenRunner());
427    }
428 
429    /**
430     * @see    #invokeLaterRefreshComicView()
431     */
432    private void refreshDisplay() {
433        if (Boolean.getBoolean(PropertyConstants.SYSTEM_PROPERTY_PREFIX + PropertyConstants.TEST_BEEP_ON_REPAINT)) {
434            jomicTools.beep();
435        }
436        if (isVisible()) {
437            int screenWidth = frame.getWidth();
438            int screenHeight = frame.getHeight();
439            BufferStrategy bufferStrategy = frame.getBufferStrategy();
440            Graphics2D g2d = (Graphics2D) bufferStrategy.getDrawGraphics();
441            try {
442                ComicSheet comicSheet = comicView.getSheetForPage(comicView.getPage());
443                int imageIndex = controller.getComicView().getImageIndex();
444                int leftImageIndex = comicSheet.getLeftImageIndex();
445                RenderedImage leftImage = comicView.getComicImage(leftImageIndex).getImage();
446                RenderedImage rightImage = null;
447 
448                if (comicSheet.hasRightImage()) {
449                    int rightImageIndex = comicSheet.getRightImageIndex();
450 
451                    rightImage = comicView.getComicImage(rightImageIndex).getImage();
452                }
453 
454                if (settings.useBlur()) {
455                    String blurMode = settings.getBlurMode();
456                    leftImage = imageTools.getBluredImage(leftImage, blurMode);
457                    if (rightImage != null) {
458                        rightImage = imageTools.getBluredImage(rightImage, blurMode);
459                    }
460                }
461 
462                ComicSheetLayout renderer = new ComicSheetLayout();
463                ComicSheetRenderSettings renderSettings = new ComicSheetRenderSettings();
464 
465                renderSettings.setTwoPageMode(settings.getTwoPageMode());
466                renderSettings.setSwapLeftAndRightImage(settings.getSwapLeftAndRightImage());
467                renderSettings.setScaleMode(ImageTools.SCALE_FIT);
468                renderSettings.setRotation(controller.getComicView().getRotation());
469 
470                renderer.renderTo(g2d, screenWidth, screenHeight, imageIndex, comicSheet,
471                        leftImage, rightImage, renderSettings);
472                bufferStrategy.show();
473            } finally {
474                g2d.dispose();
475            }
476        }
477    }
478 
479    /**
480     * Runnable to cancel full-screen mode.
481     *
482     * @author    Thomas Aglassinger.
483     */
484    private final class CancelFullScreenRunner implements Runnable
485    {
486        private JomicFrame oldController;
487 
488        private CancelFullScreenRunner() {
489            oldController = controller;
490        }
491 
492        public void run() {
493            setVisible(false);
494            if (oldController != null) {
495                oldController.getComicView().updateDisplay();
496                oldController.setVisible(true);
497            }
498        }
499    }
500 
501    /**
502     *  Runnable to delegate ActionEvent to owning JomicFrame to keep it up to date.
503     *
504     * @author    Thomas Aglassinger.
505     */
506    private final class DelegateActionToControllerRunner implements Runnable
507    {
508        private ActionEvent eventToDelegate;
509 
510        private DelegateActionToControllerRunner(ActionEvent newEventToDelegate) {
511            super();
512            eventToDelegate = newEventToDelegate;
513        }
514 
515        public void run() {
516            controller.actionPerformed(eventToDelegate);
517        }
518    }
519 
520    /**
521     *  Runnable to refresh full-screen display.
522     *
523     * @author Thomas Aglassinger
524     */
525    private final class RefreshDisplayRunner implements Runnable
526    {
527        public RefreshDisplayRunner() {
528            super();
529        }
530 
531        public void run() {
532            refreshDisplay();
533        }
534    }
535 
536    /**
537     *  Runnable to show error.
538     *
539     * @author    Thomas Aglassinger.
540     */
541    private final class ShowErrorRunner implements Runnable
542    {
543        private ActionEvent actionToReport;
544        private Throwable errorToReport;
545 
546        private ShowErrorRunner(ActionEvent newActionToReport, Throwable newErrorToReport) {
547            super();
548            actionToReport = newActionToReport;
549            errorToReport = newErrorToReport;
550        }
551 
552        public void run() {
553            jomicTools.showError(actionToReport, errorToReport);
554        }
555    }
556 
557    public void keyTyped(KeyEvent keyEvent) {
558        // Do nothing.
559    }
560 
561    /**
562     * Check if <code>keyEvent</code> can be processed and if so, convert it
563     * to an <code>ActionEvent</code> and handle it.
564     *
565     * @see #actionPerformed(ActionEvent)
566     */
567    public void keyPressed(KeyEvent keyEvent) {
568        KeyStroke keyStroke = KeyStroke.getKeyStrokeForEvent(keyEvent);
569 
570        logger.debug("key pressed: " + keyStroke);
571        String command = (String) keyStrokeToCommandMap.get(keyStroke);
572        if (command != null) {
573            ActionEvent actionEvent = new ActionEvent(keyEvent.getSource(), ActionEvent.ACTION_PERFORMED, command);
574 
575            actionPerformed(actionEvent);
576        } else {
577            logger.debug("ignoring unknown key stroke: " + keyStroke);
578        }
579    }
580 
581    public void keyReleased(KeyEvent keyEvent) {
582        // Do nothing.
583    }
584 
585    public void mouseClicked(MouseEvent mouseEvent) {
586        // Do nothing.
587    }
588 
589    public void mouseEntered(MouseEvent mouseEvent) {
590        // Do nothing.
591    }
592 
593    public void mouseExited(MouseEvent mouseEvent) {
594        // Do nothing.
595    }
596 
597    public void mousePressed(MouseEvent mouseEvent) {
598        // Do nothing.
599    }
600 
601    public void mouseReleased(MouseEvent mouseEvent) {
602        if (SwingUtilities.isLeftMouseButton(mouseEvent)) {
603            if (ignoreNextLeftMouseButtonReleased) {
604                // Right mouse button was pressed with left mouse button down just before, so there
605                // is no point in going forward right now.
606                ignoreNextLeftMouseButtonReleased = false;
607            } else {
608                ActionEvent actionEvent = new ActionEvent(mouseEvent.getSource(),
609                        ActionEvent.ACTION_PERFORMED, Commands.ADVANCE);
610                actionPerformed(actionEvent);
611            }
612        } else if (SwingUtilities.isRightMouseButton(mouseEvent)) {
613            boolean leftButtonDown = (mouseEvent.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0;
614 
615            if (leftButtonDown) {
616                ActionEvent actionEvent = new ActionEvent(mouseEvent.getSource(),
617                        ActionEvent.ACTION_PERFORMED, Commands.RETREAT);
618                actionPerformed(actionEvent);
619                ignoreNextLeftMouseButtonReleased = true;
620            }
621        }
622    }
623}

[all classes][net.sf.jomic.ui]
EMMA 2.0.4217 (C) Vladimir Roubtsov