001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.image;
043:
044: import java.awt.BorderLayout;
045: import java.awt.Color;
046: import java.awt.Component;
047: import java.awt.Dimension;
048: import java.awt.Graphics;
049: import java.awt.Image;
050: import java.awt.event.ActionListener;
051: import java.awt.event.ActionEvent;
052: import java.beans.PropertyChangeEvent;
053: import java.beans.PropertyChangeListener;
054: import java.io.IOException;
055: import java.io.ObjectInput;
056: import java.io.ObjectOutput;
057: import java.util.ArrayList;
058: import java.util.Collection;
059: import java.util.HashSet;
060: import java.util.Iterator;
061: import java.util.Set;
062: import javax.swing.JButton;
063: import javax.swing.JLabel;
064: import javax.swing.JPanel;
065: import javax.swing.JScrollPane;
066: import javax.swing.JToolBar;
067: import org.openide.filesystems.FileObject;
068: import org.openide.filesystems.FileUtil;
069: import org.openide.loaders.DataObject;
070: import org.openide.text.CloneableEditorSupport;
071: import org.openide.util.*;
072: import org.openide.util.actions.SystemAction;
073: import org.openide.windows.CloneableTopComponent;
074: import org.openide.windows.Mode;
075: import org.openide.windows.TopComponent;
076: import org.openide.windows.WindowManager;
077: import org.openide.windows.Workspace;
078:
079: /**
080: * Top component providing a viewer for images.
081: * @author Petr Hamernik, Ian Formanek, Lukas Tadial
082: * @author Marian Petras
083: */
084: public class ImageViewer extends CloneableTopComponent {
085:
086: /** Serialized version UID. */
087: static final long serialVersionUID = 6960127954234034486L;
088:
089: /** <code>ImageDataObject</code> which image is viewed. */
090: private ImageDataObject storedObject;
091:
092: /** Viewed image. */
093: private NBImageIcon storedImage;
094:
095: /** Component showing image. */
096: private JPanel panel;
097:
098: /** Scale of image. */
099: private double scale = 1.0D;
100:
101: /** On/off grid. */
102: private boolean showGrid = false;
103:
104: /** Increase/decrease factor. */
105: private final double changeFactor = Math.sqrt(2.0D);
106:
107: /** Grid color. */
108: private final Color gridColor = Color.black;
109:
110: /** Listens for name changes. */
111: private PropertyChangeListener nameChangeL;
112:
113: /** collection of all buttons in the toolbar */
114: private final Collection/*<JButton>*/toolbarButtons = new ArrayList/*<JButton>*/(
115: 11);
116:
117: /** Default constructor. Must be here, used during de-externalization */
118: public ImageViewer() {
119: super ();
120: }
121:
122: /** Create a new image viewer.
123: * @param obj the data object holding the image
124: */
125: public ImageViewer(ImageDataObject obj) {
126: initialize(obj);
127: }
128:
129: /** Overriden to explicitely set persistence type of ImageViewer
130: * to PERSISTENCE_ONLY_OPENED */
131: public int getPersistenceType() {
132: return TopComponent.PERSISTENCE_ONLY_OPENED;
133: }
134:
135: /** Reloads icon. */
136: protected void reloadIcon() {
137: resizePanel();
138: panel.repaint();
139: }
140:
141: /** Initializes member variables and set listener for name changes on DataObject. */
142: private void initialize(ImageDataObject obj) {
143: TopComponent.NodeName.connect(this , obj.getNodeDelegate());
144: setToolTipText(FileUtil
145: .getFileDisplayName(obj.getPrimaryFile()));
146:
147: storedObject = obj;
148:
149: // force closing panes in all workspaces, default is in current only
150: setCloseOperation(TopComponent.CLOSE_EACH);
151:
152: /* try to load the image: */
153: String errMsg = loadImage(storedObject);
154:
155: /* compose the whole panel: */
156: JToolBar toolbar = createToolBar();
157: Component view;
158: if (storedImage != null) {
159: view = createImageView();
160: } else {
161: view = createMessagePanel(errMsg);
162: setToolbarButtonsEnabled(false);
163: }
164: setLayout(new BorderLayout());
165: add(view, BorderLayout.CENTER);
166: add(toolbar, BorderLayout.NORTH);
167:
168: getAccessibleContext().setAccessibleDescription(
169: NbBundle.getBundle(ImageViewer.class).getString(
170: "ACS_ImageViewer"));
171:
172: nameChangeL = new PropertyChangeListener() {
173: public void propertyChange(PropertyChangeEvent evt) {
174: if (DataObject.PROP_COOKIE
175: .equals(evt.getPropertyName())
176: || DataObject.PROP_NAME.equals(evt
177: .getPropertyName())) {
178: updateName();
179: }
180: }
181: };
182:
183: obj.addPropertyChangeListener(WeakListeners.propertyChange(
184: nameChangeL, obj));
185: }
186:
187: /**
188: */
189: private Component createImageView() {
190: panel = new JPanel() {
191: protected void paintComponent(Graphics g) {
192: super .paintComponent(g);
193: g
194: .drawImage(storedImage.getImage(), 0, 0,
195: (int) (getScale() * storedImage
196: .getIconWidth()),
197: (int) (getScale() * storedImage
198: .getIconHeight()), 0, 0,
199: storedImage.getIconWidth(), storedImage
200: .getIconHeight(), this );
201:
202: if (showGrid) {
203: int x = (int) (getScale() * storedImage
204: .getIconWidth());
205: int y = (int) (getScale() * storedImage
206: .getIconHeight());
207:
208: double gridDistance = getScale();
209:
210: if (gridDistance < 2)
211: // Disable painting of grid if no image pixels would be visible.
212: return;
213:
214: g.setColor(gridColor);
215:
216: double actualDistance = gridDistance;
217: for (int i = (int) actualDistance; i < x; actualDistance += gridDistance, i = (int) actualDistance) {
218: g.drawLine(i, 0, i, (y - 1));
219: }
220:
221: actualDistance = gridDistance;
222: for (int j = (int) actualDistance; j < y; actualDistance += gridDistance, j = (int) actualDistance) {
223: g.drawLine(0, j, (x - 1), j);
224: }
225: }
226:
227: }
228:
229: };
230: // vlv: print
231: panel.putClientProperty(java.awt.print.Printable.class,
232: getToolTipText());
233:
234: storedImage.setImageObserver(panel);
235: panel
236: .setPreferredSize(new Dimension(storedImage
237: .getIconWidth(), storedImage.getIconHeight()));
238:
239: return new JScrollPane(panel);
240: }
241:
242: /**
243: */
244: private Component createMessagePanel(final String msg) {
245: JPanel msgPanel = new JPanel(new java.awt.GridBagLayout());
246: msgPanel.add(new JLabel(msg), new java.awt.GridBagConstraints(
247: 0, 0, //gridx, gridy
248: 1, 1, //gridwidth, gridheight
249: 1.0d, 1.0d, //weightx, weighty
250: java.awt.GridBagConstraints.CENTER, //anchor
251: java.awt.GridBagConstraints.NONE, //fill
252: new java.awt.Insets(0, 0, 0, 0), //insets
253: 10, 10)); //ipadx, ipady
254: return msgPanel;
255: }
256:
257: /**
258: */
259: void updateView(final ImageDataObject imageObj) {
260: boolean wasValid = (storedImage != null);
261: String errMsg = loadImage(imageObj);
262: boolean isValid = (storedImage != null);
263:
264: if (wasValid && isValid) {
265: reloadIcon();
266: return;
267: }
268:
269: Component view = (storedImage != null) ? createImageView()
270: : createMessagePanel(errMsg);
271: remove(0);
272: add(view, BorderLayout.CENTER, 0);
273: if (wasValid != isValid) {
274: setToolbarButtonsEnabled(isValid);
275: }
276: }
277:
278: /**
279: * Enables or disables all toolbar buttons.
280: *
281: * @param enabled <code>true</code> if all buttons should be enabled,
282: * <code>false</code> if all buttons should be disabled
283: */
284: private void setToolbarButtonsEnabled(final boolean enabled) {
285: assert toolbarButtons != null;
286:
287: final Iterator/*<JButton>*/it = toolbarButtons.iterator();
288: while (it.hasNext()) {
289: ((JButton) it.next()).setEnabled(enabled);
290: }
291: }
292:
293: /**
294: * Loads an image from the given <code>ImageDataObject</code>.
295: * If the image is loaded successfully, it is stored
296: * to field {@link #storedImage}. The field is <code>null</code>ed
297: * in case of any failure.
298: *
299: * @param imageObj <code>ImageDataObject</code> to load the image from
300: * @return <code>null</code> if the image was loaded successfully,
301: * or a localized error message in case of failure
302: */
303: private String loadImage(final ImageDataObject imageObj) {
304: String errMsg;
305: try {
306: storedImage = NBImageIcon.load(imageObj);
307: if (storedImage != null) {
308: errMsg = null;
309: } else {
310: errMsg = NbBundle.getMessage(ImageViewer.class,
311: "MSG_CouldNotLoad"); //NOI18N
312: }
313: } catch (IOException ex) {
314: storedImage = null;
315: errMsg = NbBundle.getMessage(ImageViewer.class,
316: "MSG_ErrorWhileLoading"); //NOI18N
317: }
318: assert (storedImage == null) != (errMsg == null);
319: return errMsg;
320: }
321:
322: /** Creates toolbar. */
323: private JToolBar createToolBar() {
324: // Definition of toolbar.
325: JToolBar toolBar = new JToolBar();
326: toolBar.setFloatable(false);
327: toolBar.setName(NbBundle.getBundle(ImageViewer.class)
328: .getString("ACSN_Toolbar"));
329: toolBar.getAccessibleContext().setAccessibleDescription(
330: NbBundle.getBundle(ImageViewer.class).getString(
331: "ACSD_Toolbar"));
332: JButton outButton = new JButton(SystemAction
333: .get(ZoomOutAction.class));
334: outButton.setToolTipText(NbBundle.getBundle(ImageViewer.class)
335: .getString("LBL_ZoomOut"));
336: outButton.setMnemonic(NbBundle.getBundle(ImageViewer.class)
337: .getString("ACS_Out_BTN_Mnem").charAt(0));
338: outButton.getAccessibleContext().setAccessibleDescription(
339: NbBundle.getBundle(ImageViewer.class).getString(
340: "ACSD_Out_BTN"));
341: outButton.setText("");
342: toolBar.add(outButton);
343: toolbarButtons.add(outButton);
344: toolBar.addSeparator(new Dimension(2, 2));
345: JButton inButton = new JButton(SystemAction
346: .get(ZoomInAction.class));
347: inButton.setToolTipText(NbBundle.getBundle(ImageViewer.class)
348: .getString("LBL_ZoomIn"));
349: inButton.setMnemonic(NbBundle.getBundle(ImageViewer.class)
350: .getString("ACS_In_BTN_Mnem").charAt(0));
351: inButton.getAccessibleContext().setAccessibleDescription(
352: NbBundle.getBundle(ImageViewer.class).getString(
353: "ACSD_In_BTN"));
354: inButton.setText("");
355: toolBar.add(inButton);
356: toolbarButtons.add(inButton);
357: toolBar.addSeparator(new Dimension(11, 2));
358:
359: JButton button;
360:
361: toolBar.add(button = getZoomButton(1, 1));
362: toolbarButtons.add(button);
363: toolBar.addSeparator(new Dimension(11, 2));
364: toolBar.add(button = getZoomButton(1, 3));
365: toolbarButtons.add(button);
366: toolBar.addSeparator(new Dimension(2, 2));
367: toolBar.add(button = getZoomButton(1, 5));
368: toolbarButtons.add(button);
369: toolBar.addSeparator(new Dimension(2, 2));
370: toolBar.add(button = getZoomButton(1, 7));
371: toolbarButtons.add(button);
372: toolBar.addSeparator(new Dimension(11, 2));
373: toolBar.add(button = getZoomButton(3, 1));
374: toolbarButtons.add(button);
375: toolBar.addSeparator(new Dimension(2, 2));
376: toolBar.add(button = getZoomButton(5, 1));
377: toolbarButtons.add(button);
378: toolBar.addSeparator(new Dimension(2, 2));
379: toolBar.add(button = getZoomButton(7, 1));
380: toolbarButtons.add(button);
381: toolBar.addSeparator(new Dimension(11, 2));
382: // SystemAction sa = SystemAction.get(CustomZoomAction.class);
383: // sa.putValue (Action.SHORT_DESCRIPTION, NbBundle.getBundle(ImageViewer.class).getString("LBL_CustomZoom"));
384: toolBar.add(button = getZoomButton());
385: toolbarButtons.add(button);
386: toolBar.addSeparator(new Dimension(11, 2));
387: toolBar.add(button = getGridButton());
388: toolbarButtons.add(button);
389:
390: return toolBar;
391: }
392:
393: /** Updates the name and tooltip of this top component according to associated data object. */
394: private void updateName() {
395: // update name
396: String name = storedObject.getNodeDelegate().getDisplayName();
397: setName(name);
398: // update tooltip
399: FileObject fo = storedObject.getPrimaryFile();
400: setToolTipText(FileUtil.getFileDisplayName(fo));
401: }
402:
403: /** Docks the table into the workspace if top component is valid.
404: * (Top component may become invalid after deserialization)
405: */
406: public void open(Workspace workspace) {
407: if (discard())
408: return;
409:
410: Workspace realWorkspace = (workspace == null) ? WindowManager
411: .getDefault().getCurrentWorkspace() : workspace;
412: dockIfNeeded(realWorkspace);
413: boolean modeVisible = false;
414: TopComponent[] tcArray = editorMode(realWorkspace)
415: .getTopComponents();
416: for (int i = 0; i < tcArray.length; i++) {
417: if (tcArray[i].isOpened(realWorkspace)) {
418: modeVisible = true;
419: break;
420: }
421: }
422: if (!modeVisible) {
423: openOtherEditors(realWorkspace);
424: }
425: super .open(workspace);
426: openOnOtherWorkspaces(realWorkspace);
427: }
428:
429: /**
430: */
431: protected String preferredID() {
432: return getClass().getName();
433: }
434:
435: private void super Open(Workspace workspace) {
436: super .open(workspace);
437: }
438:
439: /** Utility method, opens this top component on all workspaces
440: * where editor mode is visible and which differs from given
441: * workspace. */
442: private void openOnOtherWorkspaces(Workspace workspace) {
443: Workspace[] workspaces = WindowManager.getDefault()
444: .getWorkspaces();
445: Mode curEditorMode = null;
446: Mode tcMode = null;
447: for (int i = 0; i < workspaces.length; i++) {
448: // skip given workspace
449: if (workspaces[i].equals(workspace)) {
450: continue;
451: }
452: curEditorMode = workspaces[i]
453: .findMode(CloneableEditorSupport.EDITOR_MODE);
454: tcMode = workspaces[i].findMode(this );
455: if (!isOpened(workspaces[i]) && curEditorMode != null
456: && (tcMode == null || tcMode.equals(curEditorMode))) {
457: // candidate for opening, but mode must be already visible
458: // (= some opened top component in it)
459: TopComponent[] tcArray = curEditorMode
460: .getTopComponents();
461: for (int j = 0; j < tcArray.length; j++) {
462: if (tcArray[j].isOpened(workspaces[i])) {
463: // yep, open this top component on found workspace too
464: pureOpen(this , workspaces[i]);
465: break;
466: }
467: }
468: }
469: }
470: }
471:
472: /** Utility method, opens top components which are opened
473: * in editor mode on some other workspace.
474: * This method should be called only if first top component is
475: * being opened in editor mode on given workspace */
476: private void openOtherEditors(Workspace workspace) {
477: // choose candidates for opening
478: Set topComps = new HashSet(15);
479: Workspace[] wsArray = WindowManager.getDefault()
480: .getWorkspaces();
481: Mode curEditorMode = null;
482: TopComponent[] tcArray = null;
483: for (int i = 0; i < wsArray.length; i++) {
484: curEditorMode = wsArray[i]
485: .findMode(CloneableEditorSupport.EDITOR_MODE);
486: if (curEditorMode != null) {
487: tcArray = curEditorMode.getTopComponents();
488: for (int j = 0; j < tcArray.length; j++) {
489: if (tcArray[j].isOpened(wsArray[i])) {
490: topComps.add(tcArray[j]);
491: }
492: }
493: }
494: }
495: // open choosed candidates
496: for (Iterator iter = topComps.iterator(); iter.hasNext();) {
497: pureOpen((TopComponent) iter.next(), workspace);
498: }
499: }
500:
501: /** Utility method, calls super version of open if given
502: * top component is of Editor type, or calls regular open otherwise.
503: * The goal is to prevent from cycle open call between
504: * Editor top components */
505: private void pureOpen(TopComponent tc, Workspace workspace) {
506: if (tc instanceof ImageViewer) {
507: ((ImageViewer) tc).dockIfNeeded(workspace);
508: ((ImageViewer) tc).super Open(workspace);
509: } else {
510: tc.open(workspace);
511: }
512: }
513:
514: /** Dock this top component to editor mode if it is not docked
515: * in some mode at this time */
516: private void dockIfNeeded(Workspace workspace) {
517: // dock into editor mode if possible
518: Mode ourMode = workspace.findMode(this );
519: if (ourMode == null) {
520: editorMode(workspace).dockInto(this );
521: }
522: }
523:
524: private Mode editorMode(Workspace workspace) {
525: Mode ourMode = workspace.findMode(this );
526: if (ourMode == null) {
527: ourMode = workspace
528: .createMode(
529: CloneableEditorSupport.EDITOR_MODE,
530: getName(),
531: CloneableEditorSupport.class
532: .getResource("/org/openide/resources/editorMode.gif" // NOI18N
533: ));
534: }
535: return ourMode;
536: }
537:
538: /** Gets HelpContext. */
539: public HelpCtx getHelpCtx() {
540: return HelpCtx.DEFAULT_HELP;
541: }
542:
543: /** This component should be discarded if the associated environment
544: * is not valid.
545: */
546: private boolean discard() {
547: return storedObject == null;
548: }
549:
550: /** Serialize this top component. Serializes its data object in addition
551: * to common superclass behaviour.
552: * @param out the stream to serialize to
553: */
554: public void writeExternal(ObjectOutput out) throws IOException {
555: super .writeExternal(out);
556: out.writeObject(storedObject);
557: }
558:
559: /** Deserialize this top component.
560: * Reads its data object and initializes itself in addition
561: * to common superclass behaviour.
562: * @param in the stream to deserialize from
563: */
564: public void readExternal(ObjectInput in) throws IOException,
565: ClassNotFoundException {
566: super .readExternal(in);
567: storedObject = (ImageDataObject) in.readObject();
568: // to reset the listener for FileObject changes
569: ((ImageOpenSupport) storedObject
570: .getCookie(ImageOpenSupport.class)).prepareViewer();
571: initialize(storedObject);
572: }
573:
574: /** Creates cloned object which uses the same underlying data object. */
575: protected CloneableTopComponent createClonedObject() {
576: return new ImageViewer(storedObject);
577: }
578:
579: /** Overrides superclass method. Gets actions for this top component. */
580: public SystemAction[] getSystemActions() {
581: SystemAction[] oldValue = super .getSystemActions();
582: SystemAction fsa = null;
583: try {
584: ClassLoader l = (ClassLoader) Lookup.getDefault().lookup(
585: ClassLoader.class);
586: if (l == null) {
587: l = getClass().getClassLoader();
588: }
589: Class c = Class.forName(
590: "org.openide.actions.FileSystemAction", true, l)
591: .asSubclass(SystemAction.class); // NOI18N
592: fsa = (SystemAction) SystemAction.findObject(c, true);
593: } catch (Exception ex) {
594: // there are no filesystem actions
595: }
596:
597: return SystemAction.linkActions(new SystemAction[] {
598: SystemAction.get(ZoomInAction.class),
599: SystemAction.get(ZoomOutAction.class),
600: SystemAction.get(CustomZoomAction.class), fsa, null },
601: oldValue);
602: }
603:
604: /** Overrides superclass method. Gets <code>Icon</code>. */
605: public Image getIcon() {
606: return Utilities
607: .loadImage("org/netbeans/modules/image/imageObject.png"); // NOI18N
608: }
609:
610: /** Draws zoom in scaled image. */
611: public void zoomIn() {
612: scaleIn();
613: resizePanel();
614: panel.repaint(0, 0, panel.getWidth(), panel.getHeight());
615: }
616:
617: /** Draws zoom out scaled image. */
618: public void zoomOut() {
619: double oldScale = scale;
620:
621: scaleOut();
622:
623: // You can't still make picture smaller, but bigger why not?
624: if (!isNewSizeOK()) {
625: scale = oldScale;
626:
627: return;
628: }
629:
630: resizePanel();
631: panel.repaint(0, 0, panel.getWidth(), panel.getHeight());
632: }
633:
634: /** Resizes panel. */
635: private void resizePanel() {
636: panel.setPreferredSize(new Dimension(
637: (int) (getScale() * storedImage.getIconWidth()),
638: (int) (getScale() * storedImage.getIconHeight())));
639: panel.revalidate();
640: }
641:
642: /** Tests new size of image. If image is smaller than minimum
643: * size(1x1) zooming will be not performed.
644: */
645: private boolean isNewSizeOK() {
646: if (((getScale() * storedImage.getIconWidth()) > 1)
647: && ((getScale() * storedImage.getIconWidth()) > 1))
648: return true;
649: return false;
650: }
651:
652: /** Perform zoom with specific proportion.
653: * @param fx numerator for scaled
654: * @param fy denominator for scaled
655: */
656: public void customZoom(int fx, int fy) {
657: double oldScale = scale;
658:
659: scale = (double) fx / (double) fy;
660: if (!isNewSizeOK()) {
661: scale = oldScale;
662:
663: return;
664: }
665:
666: resizePanel();
667: panel.repaint(0, 0, panel.getWidth(), panel.getHeight());
668: }
669:
670: /** Return zooming factor.*/
671: private double getScale() {
672: return scale;
673: }
674:
675: /** Change proportion "out"*/
676: private void scaleOut() {
677: scale = scale / changeFactor;
678: }
679:
680: /** Change proportion "in"*/
681: private void scaleIn() {
682: double oldComputedScale = getScale();
683:
684: scale = changeFactor * scale;
685:
686: double newComputedScale = getScale();
687:
688: if (newComputedScale == oldComputedScale)
689: // Has to increase.
690: scale = newComputedScale + 1.0D;
691: }
692:
693: /** Gets zoom button. */
694: private JButton getZoomButton(final int xf, final int yf) {
695: // PENDING buttons should have their own icons.
696: JButton button = new JButton("" + xf + ":" + yf); // NOI18N
697: if (xf < yf)
698: button.setToolTipText(NbBundle.getBundle(ImageViewer.class)
699: .getString("LBL_ZoomOut")
700: + " " + xf + " : " + yf);
701: else
702: button.setToolTipText(NbBundle.getBundle(ImageViewer.class)
703: .getString("LBL_ZoomIn")
704: + " " + xf + " : " + yf);
705: button.getAccessibleContext().setAccessibleDescription(
706: NbBundle.getBundle(ImageViewer.class).getString(
707: "ACS_Zoom_BTN"));
708: button.addActionListener(new ActionListener() {
709: public void actionPerformed(ActionEvent evt) {
710: customZoom(xf, yf);
711: }
712: });
713:
714: return button;
715: }
716:
717: private JButton getZoomButton() {
718: // PENDING buttons should have their own icons.
719: JButton button = new JButton(NbBundle.getBundle(
720: CustomZoomAction.class).getString("LBL_XtoY")); // NOI18N
721: button.setToolTipText(NbBundle.getBundle(ImageViewer.class)
722: .getString("LBL_CustomZoom"));
723: button.getAccessibleContext().setAccessibleDescription(
724: NbBundle.getBundle(ImageViewer.class).getString(
725: "ACS_Zoom_BTN"));
726: button.addActionListener(new ActionListener() {
727: public void actionPerformed(ActionEvent evt) {
728: CustomZoomAction sa = (CustomZoomAction) SystemAction
729: .get(CustomZoomAction.class);
730: sa.performAction();
731: }
732: });
733:
734: return button;
735: }
736:
737: /** Gets grid button.*/
738: private JButton getGridButton() {
739: // PENDING buttons should have their own icons.
740: final JButton button = new JButton(" # "); // NOI18N
741: button.setToolTipText(NbBundle.getBundle(ImageViewer.class)
742: .getString("LBL_ShowHideGrid"));
743: button.getAccessibleContext().setAccessibleDescription(
744: NbBundle.getBundle(ImageViewer.class).getString(
745: "ACS_Grid_BTN"));
746: button.setMnemonic(NbBundle.getBundle(ImageViewer.class)
747: .getString("ACS_Grid_BTN_Mnem").charAt(0));
748: button.addActionListener(new ActionListener() {
749: public void actionPerformed(ActionEvent evt) {
750: showGrid = !showGrid;
751: panel
752: .repaint(0, 0, panel.getWidth(), panel
753: .getHeight());
754: }
755: });
756:
757: return button;
758: }
759:
760: }
|