EMMA Coverage Report (generated Sat Oct 08 11:41:37 CEST 2011)
[all classes][net.sf.jomic.ui]

COVERAGE SUMMARY FOR SOURCE FILE [FullScreenViewer.java]

nameclass, %method, %block, %line, %
FullScreenViewer.java33%  (2/6)50%  (18/36)57%  (695/1209)60%  (171.9/287)

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)56%  (15/27)60%  (667/1118)63%  (161.9/256)
actionPerformed (ActionEvent): void 0%   (0/1)0%   (0/162)0%   (0/34)
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)
mouseEntered (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/25)0%   (0/6)
addShortCutKey (KeyStroke, String): void 100% (1/1)39%  (11/28)75%  (3/4)
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)78%  (28/36)83%  (10/12)
<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%  (118/123)100% (24/24)
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% (4/4)100% (2/2)
isVisible (): boolean 100% (1/1)100% (3/3)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% (3/3)100% (28/28)100% (10/10)
FullScreenViewer$RefreshDisplayRunner (FullScreenViewer): void 100% (1/1)100% (6/6)100% (3/3)
dispose (): void 100% (1/1)100% (4/4)100% (2/2)
run (): void 100% (1/1)100% (18/18)100% (5/5)

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

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