Mercurial > hg > Applications > TreeVNC
comparison src/viewer_swing/java/com/glavsoft/viewer/swing/Surface.java @ 0:4689cc86d6cb
create TreeViewer2 Repository
author | Yu Taninari <you@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 03 Jul 2012 13:20:49 +0900 |
parents | |
children | 3c072f2f39bb 17b702648079 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4689cc86d6cb |
---|---|
1 // Copyright (C) 2010, 2011 GlavSoft LLC. | |
2 // All rights reserved. | |
3 // | |
4 //------------------------------------------------------------------------- | |
5 // This file is part of the TightVNC software. Please visit our Web site: | |
6 // | |
7 // http://www.tightvnc.com/ | |
8 // | |
9 // This program is free software; you can redistribute it and/or modify | |
10 // it under the terms of the GNU General Public License as published by | |
11 // the Free Software Foundation; either version 2 of the License, or | |
12 // (at your option) any later version. | |
13 // | |
14 // This program is distributed in the hope that it will be useful, | |
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 // GNU General Public License for more details. | |
18 // | |
19 // You should have received a copy of the GNU General Public License along | |
20 // with this program; if not, write to the Free Software Foundation, Inc., | |
21 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
22 //------------------------------------------------------------------------- | |
23 // | |
24 | |
25 package com.glavsoft.viewer.swing; | |
26 | |
27 import com.glavsoft.core.SettingsChangedEvent; | |
28 import com.glavsoft.drawing.Renderer; | |
29 import com.glavsoft.rfb.IChangeSettingsListener; | |
30 import com.glavsoft.rfb.IRepaintController; | |
31 import com.glavsoft.rfb.encoding.PixelFormat; | |
32 import com.glavsoft.rfb.encoding.decoder.FramebufferUpdateRectangle; | |
33 import com.glavsoft.rfb.protocol.ProtocolContext; | |
34 import com.glavsoft.rfb.protocol.ProtocolSettings; | |
35 import com.glavsoft.transport.Reader; | |
36 import com.glavsoft.viewer.Viewer; | |
37 | |
38 import javax.swing.*; | |
39 import java.awt.*; | |
40 | |
41 @SuppressWarnings("serial") | |
42 public class Surface extends JPanel implements IRepaintController, IChangeSettingsListener { | |
43 | |
44 private int width; | |
45 private int height; | |
46 private SoftCursorImpl cursor; | |
47 private RendererImpl renderer; | |
48 private MouseEventListener mouseEventListener; | |
49 private KeyEventListener keyEventListener; | |
50 private boolean showCursor; | |
51 private ModifierButtonEventListener modifierButtonListener; | |
52 private boolean isUserInputEnabled = false; | |
53 private final ProtocolContext context; | |
54 private double scaleFactor; | |
55 private final Viewer viewer; | |
56 | |
57 @Override | |
58 public boolean isDoubleBuffered() { | |
59 // TODO returning false in some reason may speed ups drawing, but may | |
60 // not. Needed in challenging. | |
61 return false; | |
62 } | |
63 | |
64 public Surface(ProtocolContext context, Viewer viewer, double scaleFactor) { | |
65 this.context = context; | |
66 this.viewer = viewer; | |
67 this.scaleFactor = scaleFactor; | |
68 init(context.getFbWidth(), context.getFbHeight()); | |
69 | |
70 if ( ! context.getSettings().isViewOnly()) { | |
71 setUserInputEnabled(true, context.getSettings().isConvertToAscii()); | |
72 } | |
73 showCursor = context.getSettings().isShowRemoteCursor(); | |
74 } | |
75 | |
76 private void setUserInputEnabled(boolean enable, boolean convertToAscii) { | |
77 if (enable == isUserInputEnabled) return; | |
78 isUserInputEnabled = enable; | |
79 if (enable) { | |
80 if (null == mouseEventListener) { | |
81 mouseEventListener = new MouseEventListener(this, context, scaleFactor); | |
82 } | |
83 addMouseListener(mouseEventListener); | |
84 addMouseMotionListener(mouseEventListener); | |
85 addMouseWheelListener(mouseEventListener); | |
86 | |
87 setFocusTraversalKeysEnabled(false); | |
88 if (null == keyEventListener) { | |
89 keyEventListener = new KeyEventListener(context); | |
90 if (modifierButtonListener != null) { | |
91 keyEventListener.addModifierListener(modifierButtonListener); | |
92 } | |
93 } | |
94 keyEventListener.setConvertToAscii(convertToAscii); | |
95 addKeyListener(keyEventListener); | |
96 enableInputMethods(false); | |
97 } else { | |
98 removeMouseListener(mouseEventListener); | |
99 removeMouseMotionListener(mouseEventListener); | |
100 removeMouseWheelListener(mouseEventListener); | |
101 removeKeyListener(keyEventListener); | |
102 } | |
103 } | |
104 | |
105 @Override | |
106 public Renderer createRenderer(Reader reader, int width, int height, PixelFormat pixelFormat) { | |
107 renderer = new RendererImpl(reader, width, height, pixelFormat); | |
108 synchronized (renderer) { | |
109 cursor = renderer.getCursor(); | |
110 } | |
111 init(renderer.getWidth(), renderer.getHeight()); | |
112 updateFrameSize(); | |
113 return renderer; | |
114 } | |
115 | |
116 private void init(int width, int height) { | |
117 this.width = width; | |
118 this.height = height; | |
119 setSize(getPreferredSize()); | |
120 } | |
121 | |
122 private void updateFrameSize() { | |
123 setSize(getPreferredSize()); | |
124 viewer.packContainer(); | |
125 requestFocus(); | |
126 } | |
127 | |
128 @Override | |
129 public void paintComponent(Graphics g) { | |
130 ((Graphics2D)g).scale(scaleFactor, scaleFactor); | |
131 ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); | |
132 synchronized (renderer) { | |
133 Image offscreenImage = renderer.getOffscreenImage(); | |
134 if (offscreenImage != null) { | |
135 g.drawImage(offscreenImage, 0, 0, null); | |
136 } | |
137 } | |
138 synchronized (cursor) { | |
139 Image cursorImage = cursor.getImage(); | |
140 if (showCursor && cursorImage != null && | |
141 (scaleFactor != 1 || | |
142 g.getClipBounds().intersects(cursor.rX, cursor.rY, cursor.width, cursor.height))) { | |
143 g.drawImage(cursorImage, cursor.rX, cursor.rY, null); | |
144 } | |
145 } | |
146 } | |
147 | |
148 @Override | |
149 public Dimension getPreferredSize() { | |
150 return new Dimension((int)(this.width * scaleFactor), (int)(this.height * scaleFactor)); | |
151 } | |
152 | |
153 @Override | |
154 public Dimension getMinimumSize() { | |
155 return getPreferredSize(); | |
156 } | |
157 | |
158 @Override | |
159 public Dimension getMaximumSize() { | |
160 return getPreferredSize(); | |
161 } | |
162 | |
163 /** | |
164 * Saves context and simply invokes native JPanel repaint method which | |
165 * asyncroniously register repaint request using invokeLater to repaint be | |
166 * runned in Swing event dispatcher thread. So may be called from other | |
167 * threads. | |
168 */ | |
169 @Override | |
170 public void repaintBitmap(FramebufferUpdateRectangle rect) { | |
171 repaintBitmap(rect.x, rect.y, rect.width, rect.height); | |
172 } | |
173 | |
174 @Override | |
175 public void repaintBitmap(int x, int y, int width, int height) { | |
176 repaint((int)(x * scaleFactor), (int)(y * scaleFactor), | |
177 (int)Math.ceil(width * scaleFactor), (int)Math.ceil(height * scaleFactor)); | |
178 } | |
179 | |
180 @Override | |
181 public void repaintCursor() { | |
182 synchronized (cursor) { | |
183 repaint((int)(cursor.oldRX * scaleFactor), (int)(cursor.oldRY * scaleFactor), | |
184 (int)Math.ceil(cursor.oldWidth * scaleFactor) + 1, (int)Math.ceil(cursor.oldHeight * scaleFactor) + 1); | |
185 repaint((int)(cursor.rX * scaleFactor), (int)(cursor.rY * scaleFactor), | |
186 (int)Math.ceil(cursor.width * scaleFactor) + 1, (int)Math.ceil(cursor.height * scaleFactor) + 1); | |
187 } | |
188 } | |
189 | |
190 @Override | |
191 public void updateCursorPosition(short x, short y) { | |
192 synchronized (cursor) { | |
193 cursor.updatePosition(x, y); | |
194 repaintCursor(); | |
195 } | |
196 } | |
197 | |
198 private void showCursor(boolean show) { | |
199 synchronized (cursor) { | |
200 showCursor = show; | |
201 } | |
202 } | |
203 | |
204 public void addModifierListener(ModifierButtonEventListener modifierButtonListener) { | |
205 this.modifierButtonListener = modifierButtonListener; | |
206 if (keyEventListener != null) { | |
207 keyEventListener.addModifierListener(modifierButtonListener); | |
208 } | |
209 } | |
210 | |
211 @Override | |
212 public void settingsChanged(SettingsChangedEvent e) { | |
213 if (ProtocolSettings.isRfbSettingsChangedFired(e)) { | |
214 ProtocolSettings settings = (ProtocolSettings) e.getSource(); | |
215 setUserInputEnabled( ! settings.isViewOnly(), settings.isConvertToAscii()); | |
216 showCursor(settings.isShowRemoteCursor()); | |
217 } else if (UiSettings.isUiSettingsChangedFired(e)) { | |
218 UiSettings settings = (UiSettings) e.getSource(); | |
219 scaleFactor = settings.getScaleFactor(); | |
220 } | |
221 mouseEventListener.setScaleFactor(scaleFactor); | |
222 updateFrameSize(); | |
223 } | |
224 | |
225 @Override | |
226 public void setPixelFormat(PixelFormat pixelFormat) { | |
227 if (renderer != null) { | |
228 renderer.initPixelFormat(pixelFormat); | |
229 } | |
230 } | |
231 | |
232 } |