Example #1
0
  @Override
  protected JComponent createExtComponent() {

    JTextComponent component = getComponent();

    // Add the scroll-pane with the component to the center
    JScrollPane scroller = new JScrollPane(component);
    scroller.getViewport().setMinimumSize(new Dimension(4, 4));

    // remove default scroll-pane border, winsys will handle borders itself
    Border empty = BorderFactory.createEmptyBorder();
    // Important:  Do not delete or use null instead, will cause
    // problems on GTK L&F.  Must set both scroller border & viewport
    // border! - Tim
    scroller.setBorder(empty);
    scroller.setViewportBorder(empty);

    if (component.getClientProperty("nbeditorui.vScrollPolicy") != null) {
      scroller.setVerticalScrollBarPolicy(
          (Integer) component.getClientProperty("nbeditorui.vScrollPolicy"));
    }
    if (component.getClientProperty("nbeditorui.hScrollPolicy") != null) {
      scroller.setHorizontalScrollBarPolicy(
          (Integer) component.getClientProperty("nbeditorui.hScrollPolicy"));
    }
    // extComponent will be a panel
    JComponent ec = new JPanel(new BorderLayout());
    ec.putClientProperty(JTextComponent.class, component);
    ec.add(scroller);

    // Initialize sidebars
    // Need to clear the cache - it's null at this point when opening file but the sidebars
    // would be reused during L&F change (see BaseTextUI.UIWatcher) which would not work properly.
    CustomizableSideBar.resetSideBars(component);
    Map<SideBarPosition, JComponent> sideBars = CustomizableSideBar.getSideBars(component);
    processSideBars(sideBars, ec);

    if (listener == null) {
      listener = new SideBarsListener(component);
      CustomizableSideBar.addChangeListener(NbEditorUtilities.getMimeType(component), listener);
    }

    // Initialize the corner component
    initGlyphCorner(scroller);

    return ec;
  }
  /** Not private because of the tests. */
  static Lookup createActionContext(JTextComponent c) {
    Lookup nodeLookup = null;
    DataObject dobj = (c != null) ? NbEditorUtilities.getDataObject(c.getDocument()) : null;
    if (dobj != null && dobj.isValid()) {
      nodeLookup = dobj.getNodeDelegate().getLookup();
    }

    Lookup ancestorLookup = null;
    for (java.awt.Component comp = c; comp != null; comp = comp.getParent()) {
      if (comp instanceof Lookup.Provider) {
        Lookup lookup = ((Lookup.Provider) comp).getLookup();
        if (lookup != null) {
          ancestorLookup = lookup;
          break;
        }
      }
    }

    Lookup componentLookup = Lookups.singleton(c);
    if (nodeLookup == null && ancestorLookup == null) {
      return componentLookup;
    } else if (nodeLookup == null) {
      return new ProxyLookup(new Lookup[] {ancestorLookup, componentLookup});
    } else if (ancestorLookup == null) {
      return new ProxyLookup(new Lookup[] {nodeLookup, componentLookup});
    }
    assert nodeLookup != null && ancestorLookup != null;

    Node node = (Node) nodeLookup.lookup(Node.class);
    boolean ancestorLookupContainsNode =
        ancestorLookup.lookup(new Lookup.Template(Node.class)).allInstances().contains(node);

    if (ancestorLookupContainsNode) {
      return new ProxyLookup(new Lookup[] {ancestorLookup, componentLookup});
    } else {
      return new ProxyLookup(new Lookup[] {nodeLookup, ancestorLookup, componentLookup});
    }
  }
  /**
   * Add the presenters (usually buttons) for the contents of the toolbar contained in the base and
   * mime folders.
   *
   * @param baseFolder folder that corresponds to "text/base"
   * @param mimeFolder target mime type folder.
   * @param toolbar toolbar being constructed.
   */
  private void addPresenters() {
    JTextComponent c = getComponent();
    String mimeType = c == null ? null : NbEditorUtilities.getMimeType(c);

    if (mimeType == null) {
      return; // Probably no component or it's not loaded properly
    }

    List<? extends MultiKeyBinding> keybindings = null;
    Lookup actionContext = null;
    List items = ToolbarActionsProvider.getToolbarItems(mimeType);

    // COMPAT: The ToolbarsActionsProvider treats 'text/base' in a special way. It
    // will list only items registered for this particular mime type, but won't
    // inherit anything else. The 'text/base' is normally empty, but could be
    // used by some legacy code.
    List oldTextBaseItems = ToolbarActionsProvider.getToolbarItems("text/base"); // NOI18N
    if (oldTextBaseItems.size() > 0) {
      items = new ArrayList(items);
      items.add(new JSeparator());
      items.addAll(oldTextBaseItems);
    }

    for (Object item : items) {
      LOG.log(Level.FINE, "Adding item {0}", item); // NOI18N

      if (item == null || item instanceof JSeparator) {
        addSeparator();
        continue;
      }

      if (item instanceof String) {
        EditorKit kit = c.getUI().getEditorKit(c);
        if (kit instanceof BaseKit) {
          Action a = ((BaseKit) kit).getActionByName((String) item);
          if (a != null) {
            if (LOG.isLoggable(Level.FINE)) {
              LOG.log(
                  Level.FINE,
                  "Item {0} converted to an editor action {1}",
                  new Object[] {item, s2s(a)}); // NOI18N
            }
            item = a;
          } else {
            // unknown action
            continue;
          }
        }
      }

      if (item instanceof ContextAwareAction) {
        if (actionContext == null) {
          Lookup context = createActionContext(c);
          actionContext = context == null ? NO_ACTION_CONTEXT : context;
        }

        if (actionContext != NO_ACTION_CONTEXT) {
          Action caa = ((ContextAwareAction) item).createContextAwareInstance(actionContext);

          // use the context aware instance only if it implements Presenter.Toolbar
          // or is a Component else fall back to the original object
          if (caa instanceof Presenter.Toolbar || caa instanceof Component) {
            if (LOG.isLoggable(Level.FINE)) {
              LOG.log(
                  Level.FINE,
                  "Item {0} converted to a context-aware Action {1}",
                  new Object[] {s2s(item), s2s(caa)}); // NOI18N
            }
            item = caa;
          }
        }
      }

      if (item instanceof Presenter.Toolbar) {
        Component presenter = ((Presenter.Toolbar) item).getToolbarPresenter();
        if (presenter != null) {
          if (LOG.isLoggable(Level.FINE)) {
            LOG.log(
                Level.FINE,
                "Item {0} converted to a Presenter.Toolbar {1}",
                new Object[] {s2s(item), s2s(presenter)}); // NOI18N
          }
          item = presenter;
        }
      }

      if (item instanceof Component) {
        add((Component) item);
        if (LOG.isLoggable(Level.FINE)) {
          LOG.log(Level.FINE, "Adding component {0}", s2s(item)); // NOI18N
        }
      } else if (item instanceof Action) {
        // Wrap action to execute on the proper text component
        // because the default fallback in TextAction.getTextComponent()
        // might not work properly if the focus was switched
        // to e.g. a JTextField and then toolbar was clicked.
        Action a = new WrapperAction(componentRef, (Action) item);

        // Try to find an icon if not present
        updateIcon(a);

        // Add the action and let the JToolbar to creat a presenter for it
        item = add(a);
        if (LOG.isLoggable(Level.FINE)) {
          LOG.log(
              Level.FINE, "Adding action {0} as {1}", new Object[] {s2s(a), s2s(item)}); // NOI18N
        }
      } else {
        // Some sort of crappy item -> ignore
        if (LOG.isLoggable(Level.FINE)) {
          LOG.log(Level.FINE, "Ignoring item {0}", s2s(item)); // NOI18N
        }
        continue;
      }

      if (item instanceof AbstractButton) {
        AbstractButton button = (AbstractButton) item;
        processButton(button);

        if (keybindings == null) {
          List<? extends MultiKeyBinding> l = getKeyBindingList();
          keybindings = l == null ? Collections.<MultiKeyBinding>emptyList() : l;
        }
        updateTooltip(button, keybindings);
        if (LOG.isLoggable(Level.FINE)) {
          LOG.log(Level.FINE, "Special treatment for button {0}", s2s(item)); // NOI18N
        }
      }
    }
  }