OSDN Git Service

Maven3対応。
[jindolf/Jindolf.git] / src / main / java / jp / sfjp / jindolf / dxchg / WebIPCDialog.java
1 /*
2  * Dialog for WebIPC
3  *
4  * License : The MIT License
5  * Copyright(c) 2009 olyutorskii
6  */
7
8 package jp.sfjp.jindolf.dxchg;
9
10 import java.awt.Container;
11 import java.awt.Frame;
12 import java.awt.GridBagConstraints;
13 import java.awt.GridBagLayout;
14 import java.awt.Insets;
15 import java.awt.datatransfer.Transferable;
16 import java.awt.event.ActionEvent;
17 import java.awt.event.ActionListener;
18 import java.awt.event.MouseAdapter;
19 import java.awt.event.MouseEvent;
20 import java.awt.event.WindowAdapter;
21 import java.awt.event.WindowEvent;
22 import java.io.IOException;
23 import java.net.URI;
24 import java.net.URISyntaxException;
25 import javax.swing.BorderFactory;
26 import javax.swing.Icon;
27 import javax.swing.JButton;
28 import javax.swing.JComponent;
29 import javax.swing.JDialog;
30 import javax.swing.JLabel;
31 import javax.swing.JOptionPane;
32 import javax.swing.JPanel;
33 import javax.swing.JTextArea;
34 import javax.swing.SwingConstants;
35 import javax.swing.TransferHandler;
36 import javax.swing.border.Border;
37 import javax.swing.border.EtchedBorder;
38 import jp.sfjp.jindolf.JreChecker;
39 import jp.sfjp.jindolf.VerInfo;
40 import jp.sfjp.jindolf.log.LogWrapper;
41 import jp.sfjp.jindolf.util.GUIUtils;
42 import jp.sfjp.jindolf.util.Monodizer;
43
44 /**
45  * Webブラウザ起動用の専用ダイアログ。
46  */
47 @SuppressWarnings("serial")
48 public class WebIPCDialog
49         extends JDialog
50         implements ActionListener {
51
52     private static final String TITLE_WWW =
53             VerInfo.getFrameTitle("URLへのアクセス確認");
54
55
56     private static final LogWrapper LOGGER = new LogWrapper();
57
58
59     private final String warnMessage;
60
61     private final JLabel info =
62             new JLabel("以下のURLへのアクセスが指示されました。");
63     private final JTextArea urltext =
64             new JTextArea("");
65     private final JButton browse =
66             new JButton("デフォルトのWebブラウザで表示");
67     private final JButton clipcopy =
68             new JButton("URLをクリップボードにコピー");
69     private final JLabel dndLabel =
70             new JLabel("…またはブラウザにDrag&Drop →");
71     private final JButton cancel =
72             new JButton("閉じる");
73
74     private final WebIPC ipc;
75
76     private URI uri;
77
78
79     /**
80      * コンストラクタ。
81      * @param owner オーナーフレーム
82      */
83     public WebIPCDialog(Frame owner){
84         super(owner);
85         setModal(true);
86
87         GUIUtils.modifyWindowAttributes(this, true, false, true);
88
89         WebIPC webipc = null;
90         if(WebIPC.isDesktopSupported()){
91             webipc = WebIPC.getWebIPC();
92             if( ! webipc.isSupported(WebIPC.Action.BROWSE) ){
93                 webipc = null;
94             }
95         }
96         this.ipc = webipc;
97
98         if(this.ipc == null){
99             if( ! JreChecker.has16Runtime() ){
100                 this.warnMessage =
101                         "この機能を利用するには、JRE1.6以上が必要です";
102             }else{
103                 this.warnMessage =
104                         "何らかの理由でこの機能は利用不可になっています";
105             }
106         }else{
107             this.warnMessage = "";
108         }
109
110         Border inside =
111                 BorderFactory.createEmptyBorder(1, 4, 1, 4);
112         Border outside =
113                 BorderFactory.createEtchedBorder(EtchedBorder.RAISED);
114         Border border =
115                 BorderFactory.createCompoundBorder(outside, inside);
116         this.urltext.setBorder(border);
117         this.urltext.setEditable(false);
118         this.urltext.setLineWrap(true);
119         this.urltext.setComponentPopupMenu(new TextPopup());
120         Monodizer.monodize(this.urltext);
121
122         this.dndLabel.setIcon(GUIUtils.getWWWIcon());
123         this.dndLabel.setHorizontalTextPosition(SwingConstants.LEFT);
124         this.dndLabel.setTransferHandler(new DnDHandler());
125         this.dndLabel.addMouseListener(new DragIgniter());
126
127         Container container = getContentPane();
128         design(container);
129
130         this.browse  .addActionListener(this);
131         this.clipcopy.addActionListener(this);
132         this.cancel  .addActionListener(this);
133
134         getRootPane().setDefaultButton(this.browse);
135         this.browse.requestFocusInWindow();
136
137         if(this.ipc == null){
138             this.browse.setToolTipText(this.warnMessage);
139         }
140
141         setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
142         addWindowListener(new WindowAdapter(){
143             @Override
144             public void windowClosing(WindowEvent event){
145                 actionCancel();
146                 return;
147             }
148         });
149
150         return;
151     }
152
153     /**
154      * Webブラウザ起動用のモーダルダイアログを表示する。
155      * @param owner オーナーフレーム
156      * @param url URL文字列
157      */
158     public static void showDialog(Frame owner, String url){
159         WebIPCDialog dialog = new WebIPCDialog(owner);
160
161         dialog.setTitle(TITLE_WWW);
162         dialog.setUrlText(url);
163         dialog.pack();
164         dialog.setLocationRelativeTo(owner);
165         dialog.setVisible(true);
166
167         return;
168     }
169
170     /**
171      * 有効なURIか判定する。
172      * @param uri URI
173      * @return 有効ならtrue
174      */
175     private static boolean isValidURI(URI uri){
176         if(uri == null) return false;
177
178         if( ! uri.isAbsolute() ) return false;
179
180         String scheme = uri.getScheme();
181         if(scheme == null) return false;
182         if(   ! scheme.equalsIgnoreCase("http")
183            && ! scheme.equalsIgnoreCase("https") ) return false;
184
185         String host = uri.getHost();
186         if(host == null) return false;
187
188         return true;
189     }
190
191     /**
192      * レイアウトを行う。
193      * @param container レイアウトコンテナ
194      */
195     private void design(Container container){
196         GridBagLayout layout = new GridBagLayout();
197         GridBagConstraints constraints = new GridBagConstraints();
198         container.setLayout(layout);
199
200         JComponent buttonPanel = buildButtonPanel();
201
202         constraints.gridwidth = GridBagConstraints.REMAINDER;
203         constraints.fill      = GridBagConstraints.HORIZONTAL;
204         constraints.insets    = new Insets(5, 5, 5, 5);
205
206         container.add(this.info,   constraints);
207         container.add(this.urltext, constraints);
208         container.add(buttonPanel,    constraints);
209         container.add(this.cancel,   constraints);
210
211         return;
212     }
213
214     /**
215      * ボタンパネルを生成する。
216      * @return ボタンパネル
217      */
218     private JComponent buildButtonPanel(){
219         JPanel buttonPanel = new JPanel();
220
221         Border border = BorderFactory.createTitledBorder(
222                             "アクセスする方法を選択してください。"
223                         );
224         buttonPanel.setBorder(border);
225
226         GridBagLayout layout = new GridBagLayout();
227         GridBagConstraints constraints = new GridBagConstraints();
228         buttonPanel.setLayout(layout);
229
230         constraints.gridwidth = GridBagConstraints.REMAINDER;
231         constraints.fill      = GridBagConstraints.HORIZONTAL;
232         constraints.insets    = new Insets(3, 3, 3, 3);
233         buttonPanel.add(this.browse,   constraints);
234         buttonPanel.add(this.clipcopy, constraints);
235
236         constraints.fill   = GridBagConstraints.NONE;
237         constraints.anchor = GridBagConstraints.EAST;
238         constraints.insets    = new Insets(10, 3, 10, 3);
239         buttonPanel.add(this.dndLabel, constraints);
240
241         return buttonPanel;
242     }
243
244     /**
245      * URL文字列を設定する。
246      * @param url URL文字列
247      */
248     public void setUrlText(String url){
249         URI uriarg = null;
250         try{
251             uriarg = new URI(url);
252         }catch(URISyntaxException e){
253             // NOTHING
254         }
255
256         this.uri = uriarg;
257         if(this.uri == null) return;
258
259         if( ! isValidURI(this.uri) ) return;
260
261         String uriText = this.uri.toASCIIString();
262         this.urltext.setText(uriText);
263
264         this.urltext.revalidate();
265         pack();
266
267         return;
268     }
269
270     /**
271      * ボタン押下リスナ。
272      * @param event ボタン押下イベント
273      */
274     public void actionPerformed(ActionEvent event){
275         Object source = event.getSource();
276         if(source == this.browse){
277             actionBrowse();
278         }else if(source == this.clipcopy){
279             actionClipboardCopy();
280         }else if(source == this.cancel){
281             actionCancel();
282         }
283         return;
284     }
285
286     /**
287      * WebブラウザでURLを表示。
288      */
289     private void actionBrowse(){
290         if(this.uri == null){
291             close();
292             return;
293         }
294
295         if(this.ipc == null){
296             String title;
297             if( ! JreChecker.has16Runtime() ){
298                 title = "新しいJavaを入手しましょう";
299             }else{
300                 title = "報告";
301             }
302             JOptionPane.showMessageDialog(
303                     this,
304                     this.warnMessage, title,
305                     JOptionPane.INFORMATION_MESSAGE);
306             return;
307         }
308
309         try{
310             try{
311                 this.ipc.browse(this.uri);
312             }catch(NullPointerException e){
313                 assert false;
314             }catch(UnsupportedOperationException e){
315                 // NOTHING
316             }catch(IOException e){
317                 // NOTHING
318             }catch(SecurityException e){
319                 // NOTHING
320             }catch(IllegalArgumentException e){
321                 // NOTHING
322             }
323             String logmsg =   "URL "
324                             + this.uri.toASCIIString()
325                             + " へのアクセスをWebブラウザに指示しました";
326             LOGGER.info(logmsg);
327         }finally{
328             close();
329         }
330
331         return;
332     }
333
334     /**
335      * URLをクリップボードにコピーする。
336      */
337     private void actionClipboardCopy(){
338         if(this.uri == null){
339             close();
340             return;
341         }
342
343         String uristring = this.uri.toASCIIString();
344
345         try{
346             ClipboardAction.copyToClipboard(uristring);
347             String logmsg =  "文字列「"
348                            + uristring
349                            + "」をクリップボードにコピーしました";
350             LOGGER.info(logmsg);
351         }finally{
352             close();
353         }
354
355         return;
356     }
357
358     /**
359      * 何もせずダイアログを閉じる。
360      */
361     private void actionCancel(){
362         close();
363         return;
364     }
365
366     /**
367      * ダイアログを閉じる。
368      */
369     private void close(){
370         setVisible(false);
371         return;
372     }
373
374     /**
375      * Drag&Dropの転送処理を管理。
376      */
377     private class DnDHandler extends TransferHandler{
378
379         /**
380          * コンストラクタ。
381          */
382         public DnDHandler(){
383             super();
384             return;
385         }
386
387         /**
388          * {@inheritDoc}
389          * コピー動作のみをサポートすることを伝える。
390          * @param comp {@inheritDoc}
391          * @return {@inheritDoc}
392          */
393         @Override
394         public int getSourceActions(JComponent comp){
395             return 0 | COPY;
396         }
397
398         /**
399          * {@inheritDoc}
400          * URIエクスポータを生成する。
401          * URIも指定される。
402          * @param comp {@inheritDoc}
403          * @return {@inheritDoc}
404          */
405         @Override
406         protected Transferable createTransferable(JComponent comp){
407             UriExporter result = new UriExporter(WebIPCDialog.this.uri);
408             return result;
409         }
410
411         /**
412          * {@inheritDoc}
413          * D&Dに成功したらダイアログを閉じる。
414          * @param source {@inheritDoc}
415          * @param data {@inheritDoc}
416          * @param action {@inheritDoc}
417          */
418         @Override
419         protected void exportDone(JComponent source,
420                                    Transferable data,
421                                    int action ){
422             if(action == NONE) return;
423
424             String logmsg =   "URL "
425                             + WebIPCDialog.this.uri.toASCIIString()
426                             + " がどこかへドラッグ&ドロップされました";
427             LOGGER.info(logmsg);
428
429             close();
430
431             return;
432         }
433
434         /**
435          * {@inheritDoc}
436          * ※ SunのJRE1.6.0_11前後では、BugID 4816922のため決して呼ばれない。
437          * @param tx {@inheritDoc}
438          * @return {@inheritDoc}
439          */
440         @Override
441         public Icon getVisualRepresentation(Transferable tx){
442             return GUIUtils.getWWWIcon();
443         }
444
445     }
446
447     /**
448      * ドラッグ開始イベント処理。
449      */
450     private static class DragIgniter extends MouseAdapter{
451
452         /**
453          * コンストラクタ。
454          */
455         public DragIgniter(){
456             super();
457             return;
458         }
459
460         /**
461          * {@inheritDoc}
462          * ドラッグ開始イベント受信。
463          * @param event {@inheritDoc}
464          */
465         @Override
466         public void mousePressed(MouseEvent event){
467             JComponent comp = (JComponent)event.getSource();
468             TransferHandler handler = comp.getTransferHandler();
469             handler.exportAsDrag(comp, event, TransferHandler.COPY);
470             return;
471         }
472
473     }
474
475 }