1 package charactermanaj.ui.util;
\r
3 import java.awt.Cursor;
\r
4 import java.awt.Dimension;
\r
5 import java.awt.Point;
\r
6 import java.awt.event.MouseAdapter;
\r
7 import java.awt.event.MouseEvent;
\r
8 import java.awt.event.MouseListener;
\r
9 import java.awt.event.MouseMotionListener;
\r
10 import java.awt.event.MouseWheelEvent;
\r
11 import java.awt.event.MouseWheelListener;
\r
13 import javax.swing.JComponent;
\r
14 import javax.swing.JScrollPane;
\r
15 import javax.swing.JViewport;
\r
16 import javax.swing.SwingUtilities;
\r
18 import charactermanaj.model.AppConfig;
\r
21 * JScrollPaneでマウスによるドラッグスクロールをサポートするためのヘルパクラス.<br>
\r
24 public class ScrollPaneDragScrollSupport {
\r
29 private JScrollPane scrollPane;
\r
32 * ホイールによるスクロールで移動する分割単位.<br>
\r
33 * 表示されているエリアをn等分割したサイズごとにスクロールする.<br>
\r
35 private int wheelDivider;
\r
38 * JScrollPaneを指定して構築する.
\r
41 public ScrollPaneDragScrollSupport(JScrollPane scrollPane) {
\r
42 if (scrollPane == null) {
\r
43 throw new IllegalArgumentException();
\r
45 this.scrollPane = scrollPane;
\r
47 AppConfig appConfig = AppConfig.getInstance();
\r
48 wheelDivider = Math.max(2, appConfig.getWheelScrollUnit());
\r
53 * スクロールが調整されるたびに新しい座標にセットし直す.<br>
\r
54 * ドラッグ中であれば非nullとなる.<br>
\r
55 * ドラッグが完了した場合、もしくはドラッグが開始されていなければnullとなる.<br>
\r
57 private Point dragPt;
\r
60 * ドラッグによるスクロールが可能か?<br>
\r
61 * 垂直・水平のいずれのスクロールバーがない状況ではドラッグは開始されない.<br>
\r
62 * @return ドラッグによるスクロールが可能である場合はtrue
\r
64 public boolean isDragScrollable() {
\r
65 JViewport vp = scrollPane.getViewport();
\r
66 Dimension viewSize = vp.getViewSize();
\r
67 Dimension visibleSize = vp.getExtentSize();
\r
68 if (viewSize.width <= visibleSize.width
\r
69 && viewSize.height <= visibleSize.height) {
\r
70 // ビューポートにビューが全部表示されていればドラッグは開始されない.
\r
77 * 現在のドラッグ位置を取得する.<br>
\r
78 * ドラッグが開始されていなければnullとなる.<br>
\r
81 public Point getDragPt() {
\r
87 * @return ドラッグ中であればtrue
\r
89 public boolean isDragging() {
\r
90 return dragPt != null;
\r
95 * @param cursor カーソル
\r
97 protected void setCursor(Cursor cursor) {
\r
98 scrollPane.setCursor(cursor);
\r
102 * ドラッグの開始または終了を行う.<br>
\r
103 * すでに開始済みで開始要求するか、開始されておらず停止要求した場合は何もしない.<br>
\r
104 * @param start 開始する場合はtrue、終了する場合はfalse
\r
105 * @param mousePt 開始位置
\r
107 public void drag(boolean start, Point mousePt) {
\r
109 if (dragPt == null) {
\r
110 JViewport vp = scrollPane.getViewport();
\r
111 Dimension viewSize = vp.getViewSize();
\r
112 Dimension visibleSize = vp.getExtentSize();
\r
113 if (viewSize.width <= visibleSize.width
\r
114 && viewSize.height <= visibleSize.height) {
\r
115 // ビューポートにビューが全部表示されていればドラッグは開始されない.
\r
122 setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
\r
125 } else if (dragPt != null) {
\r
127 // (ドラッグ解除済みであれば何もしない.)
\r
129 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
\r
135 * マウスによるドラッグによるスクロール.<br>
\r
136 * 前回位置(初回なら開始位置)との差分からスクロール量を判定する.<br>
\r
137 * @param mousePt 現在のマウス位置
\r
139 public void dragging(Point mousePt) {
\r
140 if (dragPt == null || mousePt == null) {
\r
141 // 前回値がないか今回値がない場合は何もしない.
\r
146 int diff_x = dragPt.x - mousePt.x;
\r
147 int diff_y = dragPt.y - mousePt.y;
\r
149 scroll(diff_x, diff_y);
\r
156 * マウス座標単位で指定したオフセット分スクロールする.
\r
157 * @param diff_x 水平方向スクロール数
\r
158 * @param diff_y 垂直方向スクロール数
\r
160 public void scroll(int diff_x, int diff_y) {
\r
161 if (diff_x == 0 && diff_y == 0) {
\r
165 JViewport vp = scrollPane.getViewport();
\r
166 Dimension viewSize = vp.getViewSize();
\r
167 Dimension visibleSize = vp.getExtentSize();
\r
169 Point vpt = vp.getViewPosition();
\r
175 } else if (vpt.x + visibleSize.width > viewSize.width) {
\r
177 vpt.x -= (vpt.x + visibleSize.width - viewSize.width);
\r
184 } else if (vpt.y + visibleSize.height > viewSize.height) {
\r
186 vpt.y -= (vpt.y + visibleSize.height - viewSize.height);
\r
189 vp.setViewPosition(vpt);
\r
193 * ホイールによるスクロール量の分割数.<br>
\r
194 * 表示されている領域に対してn等分割したサイズを
\r
195 * 一回あたりのスクロール量とする.<br>
\r
196 * @return スクロール量の分割数
\r
198 public int getWheelDivider() {
\r
199 return wheelDivider;
\r
202 public void setWheelFactor(int wheelDivider) {
\r
203 this.wheelDivider = Math.max(2, wheelDivider);
\r
207 * マウスホイールによる水平・垂直スクロールを行うためのコンビニエスとメソッド.<br>
\r
208 * シフトキーで水平、それ以外は垂直とする.<br>
\r
209 * @param e ホイールイベント
\r
211 public void scrollByWheel(final MouseWheelEvent e) {
\r
216 JViewport vp = scrollPane.getViewport();
\r
217 Dimension visibleSize = vp.getExtentSize();
\r
219 int rotation = e.getWheelRotation();
\r
224 if (e.isShiftDown()) {
\r
226 int unit = visibleSize.width / getWheelDivider();
\r
227 diff_x = rotation * unit;
\r
231 int unit = visibleSize.height / getWheelDivider();
\r
232 diff_y = rotation * unit;
\r
235 scroll(diff_x, diff_y);
\r
240 * セットアップしたリスナを保存するもの
\r
242 private MouseListener mouseListener;
\r
245 * セットアップしたリスナを保存するもの
\r
247 private MouseMotionListener mouseMotionListener;
\r
250 * セットアップしたリスナを保存するもの
\r
252 private MouseWheelListener mouseWheelListener;
\r
255 * リスナをセットアップしたコンポーネント
\r
257 private JComponent installTarget;
\r
260 * ドラッグの開始に相応しいボタンプレスであるか判定するためのインターフェイス.
\r
263 public interface DragPridicator {
\r
266 * このマウスイベントでドラッグ開始しても良いか?
\r
268 * @return ドラッグを開始しても良い場合はtrue
\r
270 boolean isDraggable(MouseEvent e);
\r
276 * マウスによるドラッグをサポートする、一般的なマウスリスナとマウスモーションリスナをセットアップする.<br>
\r
277 * すでに登録済みであれば何もしない.<br>
\r
278 * このメソッドはマウスリスナに特別な処理が必要ない場合に定型的な処理を代行するコンビニエスメソッドです.<br>
\r
279 * @param comp マウスリスナをセットアップするターゲットのコンポーネント
\r
280 * @param predicator マウスによるドラッグの開始を行うか判定するためのオブジェクト、nullの場合は不問
\r
282 public void installDraggingListener(final JComponent comp, final DragPridicator predicator) {
\r
283 if (comp == null) {
\r
284 throw new IllegalArgumentException();
\r
286 if (mouseListener == null) {
\r
287 mouseListener = new MouseAdapter() {
\r
289 public void mousePressed(MouseEvent e) {
\r
290 if (predicator == null || predicator.isDraggable(e)) {
\r
291 Point pt = SwingUtilities.convertPoint(
\r
292 comp, e.getPoint(), scrollPane);
\r
297 public void mouseReleased(MouseEvent e) {
\r
298 if (predicator == null || predicator.isDraggable(e)) {
\r
299 Point pt = SwingUtilities.convertPoint(
\r
300 comp, e.getPoint(), scrollPane);
\r
306 comp.addMouseListener(mouseListener);
\r
308 if (mouseMotionListener == null) {
\r
309 mouseMotionListener = new MouseMotionListener() {
\r
310 public void mouseMoved(MouseEvent e) {
\r
313 public void mouseDragged(MouseEvent e) {
\r
314 Point pt = SwingUtilities.convertPoint(
\r
315 comp, e.getPoint(), scrollPane);
\r
320 comp.addMouseMotionListener(mouseMotionListener);
\r
323 if (mouseWheelListener == null) {
\r
324 mouseWheelListener = new MouseWheelListener() {
\r
325 public void mouseWheelMoved(MouseWheelEvent e) {
\r
330 // ホイールスクロールのデフォルト設定を解除する.
\r
331 scrollPane.setWheelScrollingEnabled(false);
\r
333 comp.addMouseWheelListener(mouseWheelListener);
\r
336 installTarget = comp;
\r
340 * セットアップしたリスナを解除する.<br>
\r
341 * 登録されていない場合は何もしない.<br>
\r
343 public void uninstallDraggingListener() {
\r
344 if (mouseListener != null && installTarget != null) {
\r
345 installTarget.removeMouseListener(mouseListener);
\r
346 mouseListener = null;
\r
348 if (mouseMotionListener != null && installTarget != null) {
\r
349 installTarget.removeMouseMotionListener(mouseMotionListener);
\r
350 mouseMotionListener = null;
\r
352 if (mouseWheelListener != null && installTarget != null) {
\r
353 installTarget.removeMouseWheelListener(mouseWheelListener);
\r
354 mouseWheelListener = null;
\r