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.editor.hints;
043:
044: import java.awt.*;
045: import java.awt.event.AWTEventListener;
046: import java.awt.event.KeyEvent;
047: import java.awt.event.KeyListener;
048: import java.awt.event.MouseEvent;
049: import java.awt.event.MouseListener;
050: import java.beans.PropertyChangeEvent;
051: import java.beans.PropertyChangeListener;
052: import java.io.IOException;
053: import java.util.logging.Level;
054: import java.util.logging.LogRecord;
055: import java.util.logging.Logger;
056: import javax.swing.*;
057: import javax.swing.text.BadLocationException;
058: import javax.swing.text.Document;
059: import javax.swing.text.JTextComponent;
060: import javax.swing.text.Position;
061: import org.netbeans.api.editor.EditorRegistry;
062: import org.netbeans.editor.AnnotationDesc;
063: import org.netbeans.editor.Annotations;
064: import org.netbeans.editor.BaseDocument;
065: import org.netbeans.editor.GuardedException;
066: import org.netbeans.editor.JumpList;
067: import org.netbeans.editor.Utilities;
068: import org.netbeans.modules.editor.hints.borrowed.ListCompletionView;
069: import org.netbeans.modules.editor.hints.borrowed.ScrollCompletionPane;
070: import org.netbeans.spi.editor.hints.ChangeInfo;
071: import org.netbeans.spi.editor.hints.Fix;
072: import org.netbeans.spi.editor.hints.LazyFixList;
073: import org.openide.ErrorManager;
074: import org.openide.cookies.EditCookie;
075: import org.openide.cookies.EditorCookie;
076: import org.openide.cookies.OpenCookie;
077: import org.openide.filesystems.FileObject;
078: import org.openide.loaders.DataObject;
079: import org.openide.loaders.DataObjectNotFoundException;
080: import org.openide.text.Annotation;
081: import org.openide.util.Exceptions;
082: import org.openide.util.NbBundle;
083: import org.openide.util.RequestProcessor;
084: import org.openide.util.Task;
085: import org.openide.util.TaskListener;
086:
087: /**
088: * Responsible for painting the things the user sees that indicate available
089: * hints.
090: *
091: * @author Tim Boudreau
092: */
093: public class HintsUI implements MouseListener, KeyListener,
094: PropertyChangeListener, AWTEventListener {
095:
096: private static HintsUI INSTANCE;
097: private static final String POPUP_NAME = "hintsPopup"; // NOI18N
098:
099: public static synchronized HintsUI getDefault() {
100: if (INSTANCE == null)
101: INSTANCE = new HintsUI();
102:
103: return INSTANCE;
104: }
105:
106: static Logger UI_GESTURES_LOGGER = Logger
107: .getLogger("org.netbeans.ui.editor.hints");
108:
109: private JTextComponent comp;
110: private LazyFixList hints = new StaticFixList();
111: private Popup listPopup;
112: private Popup tooltipPopup;
113: private JLabel hintIcon;
114: private ScrollCompletionPane hintListComponent;
115: private JLabel errorTooltip;
116:
117: /** Creates a new instance of HintsUI */
118: private HintsUI() {
119: EditorRegistry.addPropertyChangeListener(this );
120: propertyChange(null);
121: }
122:
123: public JTextComponent getComponent() {
124: return comp;
125: }
126:
127: public void setHints(LazyFixList hints, JTextComponent comp,
128: boolean showPopup) {
129: if (this .hints.equals(hints) && this .comp == comp) {
130: return;
131: }
132: if (comp != this .comp || !this .hints.equals(hints)
133: && comp != null) {
134: removePopups();
135: }
136: boolean show = hints != null && comp != null/* && !hints.isEmpty()*/;
137: if (!show && this .comp != null) {
138: removePopups();
139: }
140: this .hints = hints == null ? new StaticFixList() : hints;
141: setComponent(comp);
142: if (show) {
143: showHints();
144: if (showPopup) {
145: showPopup();
146: }
147: }
148: }
149:
150: public void setComponent(JTextComponent comp) {
151: boolean change = this .comp != comp;
152: if (change) {
153: unregister();
154: this .comp = comp;
155: register();
156: }
157: }
158:
159: private void register() {
160: if (comp == null) {
161: return;
162: }
163: comp.addKeyListener(this );
164: }
165:
166: private void unregister() {
167: if (comp == null) {
168: return;
169: }
170: comp.removeKeyListener(this );
171: }
172:
173: public void removePopups() {
174: if (comp == null) {
175: return;
176: }
177: removeIconHint();
178: removePopup();
179: }
180:
181: private void removeIconHint() {
182: if (hintIcon != null) {
183: Container c = hintIcon.getParent();
184: if (c != null) {
185: Rectangle bds = hintIcon.getBounds();
186: c.remove(hintIcon);
187: c.repaint(bds.x, bds.y, bds.width, bds.height);
188: }
189: }
190: }
191:
192: private void removePopup() {
193: Toolkit.getDefaultToolkit().removeAWTEventListener(this );
194: if (listPopup != null) {
195: if (tooltipPopup != null)
196: tooltipPopup.hide();
197: tooltipPopup = null;
198: listPopup.hide();
199: if (hintListComponent != null) {
200: hintListComponent.getView().removeMouseListener(this );
201: }
202: if (errorTooltip != null) {
203: errorTooltip.removeMouseListener(this );
204: }
205: hintListComponent = null;
206: errorTooltip = null;
207: listPopup = null;
208: if (hintIcon != null)
209: hintIcon.setToolTipText(NbBundle.getMessage(
210: HintsUI.class, "HINT_Bulb")); // NOI18N
211: }
212: }
213:
214: boolean isKnownComponent(Component c) {
215: return c != null
216: && (c == comp || c == hintIcon
217: || c == hintListComponent || (c instanceof Container && ((Container) c)
218: .isAncestorOf(hintListComponent)));
219: }
220:
221: private void showHints() {
222: if (comp == null || !comp.isDisplayable() || !comp.isShowing()) {
223: return;
224: }
225: configureBounds(getHintIcon());
226: }
227:
228: private void configureBounds(JComponent jc) {
229: JRootPane pane = comp.getRootPane();
230: JLayeredPane lp = pane.getLayeredPane();
231: Rectangle r = null;
232: try {
233: int pos = javax.swing.text.Utilities.getRowStart(comp, comp
234: .getCaret().getDot());
235: r = comp.modelToView(pos);
236: } catch (BadLocationException e) {
237: setHints(null, null, false);
238: ErrorManager.getDefault().notify(e);
239: return;
240: }
241: Point p = new Point(r.x - comp.getX(), r.y);
242:
243: Dimension d = jc.getPreferredSize();
244:
245: SwingUtilities.convertPointToScreen(p, comp);
246: SwingUtilities.convertPointFromScreen(p, lp);
247: jc.setBounds(p.x, p.y, d.width, d.height);
248: lp.add(jc, JLayeredPane.POPUP_LAYER);
249: jc.setVisible(true);
250: jc.repaint();
251: }
252:
253: private JLabel getHintIcon() {
254: if (hintIcon == null) {
255: hintIcon = new JLabel();
256: hintIcon.addMouseListener(this );
257: hintIcon.setToolTipText(NbBundle.getMessage(HintsUI.class,
258: "HINT_Bulb")); // NOI18N
259: }
260: String iconBase = "org/netbeans/modules/editor/hints/resources/error.png"; //NOI18N
261: hintIcon.setIcon(new ImageIcon(org.openide.util.Utilities
262: .loadImage(iconBase)));
263: return hintIcon;
264: }
265:
266: public void showPopup() {
267: if (comp == null
268: || (hints.isComputed() && hints.getFixes().isEmpty())) {
269: return;
270: }
271: if (hintIcon != null)
272: hintIcon.setToolTipText(null);
273: // be sure that hint will hide when popup is showing
274: ToolTipManager.sharedInstance().setEnabled(false);
275: ToolTipManager.sharedInstance().setEnabled(true);
276: assert hintListComponent == null;
277: Toolkit.getDefaultToolkit().addAWTEventListener(this ,
278: AWTEvent.MOUSE_EVENT_MASK);
279:
280: try {
281: int pos = javax.swing.text.Utilities.getRowStart(comp, comp
282: .getCaret().getDot());
283: Rectangle r = comp.modelToView(pos);
284:
285: Point p = new Point(r.x + 5, r.y + 20);
286: SwingUtilities.convertPointToScreen(p, comp);
287:
288: Dimension maxSize = Toolkit.getDefaultToolkit()
289: .getScreenSize();
290: maxSize.width -= p.x;
291: maxSize.height -= p.y;
292: hintListComponent = new ScrollCompletionPane(comp, hints,
293: null, null, maxSize);
294:
295: hintListComponent.getView().addMouseListener(this );
296: hintListComponent.setName(POPUP_NAME);
297:
298: assert listPopup == null;
299: listPopup = getPopupFactory().getPopup(comp,
300: hintListComponent, p.x, p.y);
301: listPopup.show();
302: } catch (BadLocationException ble) {
303: ErrorManager.getDefault().notify(ble);
304: setHints(null, null, false);
305: }
306: }
307:
308: public void showPopup(LazyFixList fixes, String description,
309: JTextComponent component, Point position) {
310: setHints(null, null, false);
311: setComponent(component);
312:
313: if (comp == null || fixes == null)
314: return;
315:
316: this .hints = fixes;
317:
318: Point p = new Point(position);
319: SwingUtilities.convertPointToScreen(p, comp);
320:
321: if (hintIcon != null)
322: hintIcon.setToolTipText(null);
323: // be sure that hint will hide when popup is showing
324: ToolTipManager.sharedInstance().setEnabled(false);
325: ToolTipManager.sharedInstance().setEnabled(true);
326: Toolkit.getDefaultToolkit().addAWTEventListener(this ,
327: AWTEvent.MOUSE_EVENT_MASK);
328:
329: errorTooltip = new JLabel("<html>" + translate(description)); // NOI18N
330: errorTooltip.setBorder(BorderFactory.createCompoundBorder(
331: BorderFactory.createLineBorder(Color.BLACK),
332: BorderFactory.createEmptyBorder(0, 3, 0, 3)));
333: errorTooltip.addMouseListener(this );
334:
335: if (!fixes.isComputed() || fixes.getFixes().isEmpty()) {
336: //show tooltip:
337: assert listPopup == null;
338:
339: listPopup = getPopupFactory().getPopup(comp, errorTooltip,
340: p.x, p.y);
341: } else {
342: assert hintListComponent == null;
343:
344: try {
345: int pos = javax.swing.text.Utilities.getRowStart(comp,
346: comp.getCaret().getDot());
347: Rectangle r = comp.modelToView(pos);
348:
349: tooltipPopup = getPopupFactory()
350: .getPopup(
351: comp,
352: errorTooltip,
353: p.x,
354: p.y
355: - r.height
356: - errorTooltip
357: .getPreferredSize().height
358: - 5);
359: } catch (BadLocationException blE) {
360: ErrorManager.getDefault().notify(blE);
361: errorTooltip = null;
362: }
363: hintListComponent = new ScrollCompletionPane(comp, fixes,
364: null, null, getMaxSizeAt(p));
365:
366: hintListComponent.getView().addMouseListener(this );
367: hintListComponent.setName(POPUP_NAME);
368: assert listPopup == null;
369: listPopup = getPopupFactory().getPopup(comp,
370: hintListComponent, p.x, p.y);
371: }
372:
373: if (tooltipPopup != null)
374: tooltipPopup.show();
375: listPopup.show();
376: }
377:
378: private PopupFactory pf = null;
379:
380: private PopupFactory getPopupFactory() {
381: if (pf == null) {
382: pf = PopupFactory.getSharedInstance();
383: }
384: return pf;
385: }
386:
387: private Dimension getMaxSizeAt(Point p) {
388: Rectangle screenBounds = null;
389: if (null != comp && null != comp.getGraphicsConfiguration()) {
390: screenBounds = comp.getGraphicsConfiguration().getBounds();
391: } else {
392: screenBounds = new Rectangle(Toolkit.getDefaultToolkit()
393: .getScreenSize());
394: }
395: Dimension maxSize = screenBounds.getSize();
396: maxSize.width -= p.x - screenBounds.x;
397: maxSize.height -= p.y - screenBounds.y;
398: return maxSize;
399: }
400:
401: public void mouseClicked(java.awt.event.MouseEvent e) {
402: if (e.getSource() == hintListComponent
403: || e.getSource() instanceof ListCompletionView) {
404: Fix f = null;
405: Object selected = hintListComponent.getView()
406: .getSelectedValue();
407:
408: if (selected instanceof Fix) {
409: f = (Fix) selected;
410: }
411:
412: if (f != null) {
413: e.consume();
414: JTextComponent c = this .comp;
415: invokeHint(f);
416: if (c != null && org.openide.util.Utilities.isMac()) {
417: // see issue #65326
418: c.requestFocus();
419: }
420: setHints(null, null, false);
421: //the component was reset when setHints was called, set it back so further hints will work:
422: setComponent(c);
423: }
424: }
425: }
426:
427: public void mouseEntered(java.awt.event.MouseEvent e) {
428: }
429:
430: public void mouseExited(java.awt.event.MouseEvent e) {
431: }
432:
433: public void mousePressed(java.awt.event.MouseEvent e) {
434: if (e.getSource() instanceof JLabel) {
435: if (!isPopupActive()) {
436: showPopup();
437: }
438: }
439: }
440:
441: public void mouseReleased(java.awt.event.MouseEvent e) {
442: }
443:
444: public boolean isActive() {
445: boolean bulbShowing = hintIcon != null && hintIcon.isShowing();
446: boolean popupShowing = hintListComponent != null
447: && hintListComponent.isShowing();
448: return bulbShowing || popupShowing;
449: }
450:
451: public boolean isPopupActive() {
452: return hintListComponent != null
453: && hintListComponent.isShowing();
454: }
455:
456: private ParseErrorAnnotation findAnnotation(Document doc,
457: AnnotationDesc desc, int lineNum) {
458: DataObject od = (DataObject) doc
459: .getProperty(Document.StreamDescriptionProperty);
460:
461: if (od == null)
462: return null;
463:
464: AnnotationHolder annotations = AnnotationHolder.getInstance(od
465: .getPrimaryFile());
466:
467: if (annotations != null) {
468: for (Annotation a : annotations.getAnnotations()) {
469: if (a instanceof ParseErrorAnnotation) {
470: ParseErrorAnnotation pa = (ParseErrorAnnotation) a;
471:
472: if (lineNum == pa.getLineNumber()
473: && org.openide.util.Utilities
474: .compareObjects(desc
475: .getShortDescription(), a
476: .getShortDescription())) {
477: return pa;
478: }
479: }
480: }
481: }
482:
483: return null;
484: }
485:
486: boolean invokeDefaultAction() {
487: JTextComponent comp = this .comp;
488: if (comp == null) {
489: Logger
490: .getLogger(HintsUI.class.getName())
491: .log(Level.WARNING,
492: "HintsUI.invokeDefaultAction called, but comp == null");
493: return false;
494: }
495:
496: Document doc = comp.getDocument();
497:
498: if (doc instanceof BaseDocument) {
499: Annotations annotations = ((BaseDocument) doc)
500: .getAnnotations();
501:
502: try {
503: Rectangle carretRectangle = comp.modelToView(comp
504: .getCaretPosition());
505: int line = Utilities.getLineOffset((BaseDocument) doc,
506: comp.getCaretPosition());
507: AnnotationDesc desc = annotations
508: .getActiveAnnotation(line);
509: Point p = comp.modelToView(
510: Utilities.getRowStartFromLineOffset(
511: (BaseDocument) doc, line))
512: .getLocation();
513: p.y += carretRectangle.height;
514: if (comp.getParent() instanceof JViewport) {
515: p.x += ((JViewport) comp.getParent())
516: .getViewPosition().x;
517: }
518: ParseErrorAnnotation annotation = findAnnotation(doc,
519: desc, line);
520:
521: if (annotation == null)
522: return false;
523:
524: showPopup(annotation.getFixes(), annotation
525: .getDescription(), comp, p);
526:
527: return true;
528: } catch (BadLocationException ex) {
529: ErrorManager.getDefault().notify(ex);
530: }
531: }
532:
533: return false;
534: }
535:
536: public void keyPressed(KeyEvent e) {
537: if (comp == null) {
538: return;
539: }
540: boolean bulbShowing = hintIcon != null && hintIcon.isShowing();
541: boolean errorTooltipShowing = errorTooltip != null
542: && errorTooltip.isShowing();
543: boolean popupShowing = hintListComponent != null
544: && hintListComponent.isShowing();
545:
546: if (errorTooltipShowing && !popupShowing) {
547: //any key should disable the errorTooltip:
548: removePopup();
549: return;
550: }
551: if (e.getKeyCode() == KeyEvent.VK_ENTER) {
552: if (e.getModifiersEx() == (KeyEvent.CTRL_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)
553: || e.getModifiersEx() == KeyEvent.ALT_DOWN_MASK) {
554: if (!popupShowing) {
555: invokeDefaultAction();
556: e.consume();
557: }
558: } else if (e.getModifiersEx() == 0) {
559: if (popupShowing) {
560: Fix f = null;
561: Object selected = hintListComponent.getView()
562: .getSelectedValue();
563:
564: if (selected instanceof Fix) {
565: f = (Fix) selected;
566: }
567:
568: if (f != null) {
569: invokeHint(f);
570: }
571:
572: e.consume();
573: }
574: }
575: } else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
576: if (popupShowing) {
577: removePopup();
578: }
579: } else if (popupShowing) {
580: InputMap input = hintListComponent.getInputMap();
581: Object actionTag = input.get(KeyStroke
582: .getKeyStrokeForEvent(e));
583: if (actionTag != null) {
584: Action a = hintListComponent.getActionMap().get(
585: actionTag);
586: a.actionPerformed(null);
587: e.consume();
588: return;
589: } else {
590: removePopup();
591: }
592: }
593: }
594:
595: public void keyReleased(KeyEvent e) {
596: }
597:
598: public void keyTyped(KeyEvent e) {
599: }
600:
601: private ChangeInfo changes;
602:
603: private void invokeHint(final Fix f) {
604: if (UI_GESTURES_LOGGER.isLoggable(Level.FINE)) {
605: LogRecord rec = new LogRecord(Level.FINE,
606: "GEST_HINT_INVOKED");
607:
608: rec.setResourceBundle(NbBundle.getBundle(HintsUI.class));
609: rec.setParameters(new Object[] { f.getText() });
610: UI_GESTURES_LOGGER.log(rec);
611: }
612:
613: removePopups();
614: final JTextComponent component = comp;
615: JumpList.checkAddEntry(component);
616: final Cursor cur = component.getCursor();
617: component.setCursor(Cursor
618: .getPredefinedCursor(Cursor.WAIT_CURSOR));
619: Task t = null;
620: try {
621: t = RequestProcessor.getDefault().post(new Runnable() {
622: public void run() {
623: try {
624: changes = f.implement();
625: } catch (GuardedException ge) {
626: reportGuardedException(component, ge);
627: } catch (IOException e) {
628: if (e.getCause() instanceof GuardedException) {
629: reportGuardedException(component, e);
630: } else {
631: Exceptions.printStackTrace(e);
632: }
633: } catch (Exception e) {
634: Exceptions.printStackTrace(e);
635: }
636: }
637: });
638: } finally {
639: if (t != null) {
640: t.addTaskListener(new TaskListener() {
641: public void taskFinished(Task task) {
642: SwingUtilities.invokeLater(new Runnable() {
643: public void run() {
644: open(changes, component);
645: component.setCursor(cur);
646: }
647: });
648: }
649: });
650: }
651: }
652: }
653:
654: private static void reportGuardedException(
655: final JTextComponent component, final Exception e) {
656: SwingUtilities.invokeLater(new Runnable() {
657: public void run() {
658: String message = NbBundle.getMessage(HintsUI.class,
659: "ERR_CannotApplyGuarded");
660:
661: Utilities.setStatusBoldText(component, message);
662: Logger.getLogger(HintsUI.class.getName()).log(
663: Level.FINE, null, e);
664: }
665: });
666: }
667:
668: private static void open(ChangeInfo changes,
669: JTextComponent component) {
670: JTextComponent c = component;
671: if (changes != null && changes.size() > 0) {
672: ChangeInfo.Change change = changes.get(0);
673: FileObject file = change.getFileObject();
674: if (file != null) {
675: try {
676: DataObject dob = DataObject.find(file);
677:
678: EditCookie ck = dob.getCookie(EditCookie.class);
679:
680: if (ck != null) {
681: //Try EditCookie first so we don't open the form
682: //editor
683: ck.edit();
684: } else {
685: OpenCookie oc = dob.getCookie(OpenCookie.class);
686:
687: oc.open();
688: }
689: EditorCookie edit = dob
690: .getCookie(EditorCookie.class);
691:
692: JEditorPane[] panes = edit.getOpenedPanes();
693: if (panes != null && panes.length > 0) {
694: c = panes[0];
695: } else {
696: return;
697: }
698:
699: } catch (DataObjectNotFoundException donfe) {
700: Logger.getLogger(HintsUI.class.getName()).log(
701: Level.FINE, null, donfe);
702: return;
703: }
704: }
705: /////////////////////////////////
706: Position start = change.getStart();
707: Position end = change.getEnd();
708: if (start != null) {
709: c.setSelectionStart(start.getOffset());
710: }
711: if (end != null) {
712: c.setSelectionEnd(end.getOffset());
713: }
714: }
715: }
716:
717: public void propertyChange(PropertyChangeEvent e) {
718: JTextComponent active = EditorRegistry.lastFocusedComponent();
719:
720: if (getComponent() != active) {
721: setHints(null, null, false);
722: setComponent(active);
723: }
724: }
725:
726: public void eventDispatched(java.awt.AWTEvent aWTEvent) {
727: if (aWTEvent instanceof MouseEvent) {
728: MouseEvent mv = (MouseEvent) aWTEvent;
729: if (mv.getID() == MouseEvent.MOUSE_CLICKED
730: && mv.getClickCount() > 0) {
731: //#118828
732: if (!(aWTEvent.getSource() instanceof Component)) {
733: removePopup();
734: return;
735: }
736:
737: Component comp = (Component) aWTEvent.getSource();
738: Container par = SwingUtilities.getAncestorNamed(
739: POPUP_NAME, comp); //NOI18N
740: // Container barpar = SwingUtilities.getAncestorOfClass(PopupUtil.class, comp);
741: // if (par == null && barpar == null) {
742: if (par == null) {
743: removePopup();
744: }
745: }
746: }
747: }
748:
749: private static String[] c = new String[] { "&", "<", ">", "\n",
750: "\"" }; // NOI18N
751: private static String[] tags = new String[] { "&", "<",
752: ">", "<br>", """ }; // NOI18N
753:
754: private String translate(String input) {
755: for (int cntr = 0; cntr < c.length; cntr++) {
756: input = input.replaceAll(c[cntr], tags[cntr]);
757: }
758:
759: return input;
760: }
761:
762: }
|