]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.g2d/src/org/simantics/g2d/utils/CanvasUtils.java
Two rendering glitch fixes for time series charts
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / utils / CanvasUtils.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.g2d.utils;
13
14 import java.util.function.Supplier;
15
16 import org.simantics.g2d.canvas.Hints;
17 import org.simantics.g2d.canvas.ICanvasContext;
18 import org.simantics.g2d.diagram.DiagramHints;
19 import org.simantics.g2d.diagram.IDiagram;
20 import org.simantics.scenegraph.g2d.events.command.Command;
21 import org.simantics.scenegraph.g2d.events.command.CommandEvent;
22 import org.simantics.scenegraph.g2d.events.command.Commands;
23 import org.simantics.utils.threads.IThreadWorkQueue;
24 import org.simantics.utils.threads.ThreadUtils;
25
26 /**
27  * @author Toni Kalajainen
28  * @author Tuukka Lehtonen
29  */
30 public class CanvasUtils {
31
32     /**
33      * Enqueue a command in the event queue of the specified canvas context.
34      * 
35      * @param ctx queue context
36      * @param commandId ID of the command to queue
37      * 
38      * @see #sendCommand(ICanvasContext, Command)
39      */
40     public static void sendCommand(ICanvasContext ctx, String commandId)
41     {
42         sendCommand(ctx, new Command(commandId));
43     }
44
45     /**
46      * Enqueue a command in the event queue of the specified canvas context.
47      * 
48      * @param ctx queue context
49      * @param cmd the command to queue
50      */
51     public static void sendCommand(ICanvasContext ctx, Command cmd)
52     {
53         CommandEvent e = new CommandEvent(ctx, System.currentTimeMillis(), cmd);
54         ctx.getEventQueue().queueEvent(e);
55     }
56
57     /**
58      * A utility for scheduling a zoom-to-fit operation when an Eclipse
59      * workbench editor is initially opened.
60      * 
61      * <p>
62      * There are two asynchronous calls, first into the workbench (SWT) UI
63      * thread and then into the canvas context thread. This will guarantee that
64      * the parenting SWT control has been resized to its actual size instead of
65      * the initial (0,0) size which widgets start out at. In order to perform a
66      * zoom-to-fit operation we simply have to know the bounds of the parenting
67      * control. Thus, we need to ensure that this information is available and
68      * correct.
69      * 
70      * @param swtThread
71      * @param disposed
72      * @param canvasContext
73      * @param diagramToFit
74      */
75     public static void scheduleZoomToFit(IThreadWorkQueue swtThread, final Supplier<Boolean> disposed,
76             final ICanvasContext canvasContext, final IDiagram diagramToFit)
77     {
78         scheduleZoomToFit(swtThread, disposed, canvasContext, diagramToFit, true);
79     }
80
81     /**
82      * A utility for scheduling a zoom-to-fit operation when an Eclipse
83      * workbench editor is initially opened.
84      * 
85      * <p>
86      * There are two asynchronous calls, first into the workbench (SWT) UI
87      * thread and then into the canvas context thread. This will guarantee that
88      * the parenting SWT control has been resized to its actual size instead of
89      * the initial (0,0) size which widgets start out at. In order to perform a
90      * zoom-to-fit operation we simply have to know the bounds of the parenting
91      * control. Thus, we need to ensure that this information is available and
92      * correct.
93      * 
94      * @param swtThread
95      * @param disposed
96      * @param canvasContext
97      * @param diagramToFit
98      * @param zoomToFit
99      */
100     public static void scheduleZoomToFit(IThreadWorkQueue swtThread, final Supplier<Boolean> disposed,
101             final ICanvasContext canvasContext, final IDiagram diagramToFit, boolean zoomToFit)
102     {
103         if (diagramToFit == null)
104             throw new IllegalStateException("source diagram is null");
105
106         Boolean canvasZoomToFit = canvasContext.getHintStack().getHint(DiagramHints.KEY_INITIAL_ZOOM_TO_FIT);
107         diagramToFit.setHint(Hints.KEY_DISABLE_PAINTING, Boolean.TRUE);
108         if (zoomToFit && !Boolean.FALSE.equals(canvasZoomToFit))
109             diagramToFit.setHint(DiagramHints.KEY_INITIAL_ZOOM_TO_FIT, Boolean.TRUE);
110
111         ThreadUtils.asyncExec(swtThread, new Runnable() {
112             @Override
113             public void run() {
114                 if (disposed.get() || canvasContext.isDisposed())
115                     return;
116
117                 ThreadUtils.asyncExec(canvasContext.getThreadAccess(), new Runnable() {
118                     @Override
119                     public void run() {
120                         if (disposed.get() || canvasContext.isDisposed())
121                             return;
122
123                         Boolean zoomToFit = diagramToFit.removeHint(DiagramHints.KEY_INITIAL_ZOOM_TO_FIT);
124                         diagramToFit.removeHint(Hints.KEY_DISABLE_PAINTING);
125
126                         if (Boolean.TRUE.equals(zoomToFit))
127                             CanvasUtils.sendCommand(canvasContext, Commands.ZOOM_TO_FIT);
128                         CanvasUtils.sendCommand(canvasContext, Commands.ENABLE_PAINTING);
129                     }
130                 });
131             }
132         });
133     }
134
135 }