Google Tag Manager

Showing posts with label JPanel. Show all posts
Showing posts with label JPanel. Show all posts

2017/05/30

aterai

Use JComboBox as JTree's node cell editor

Code

class PluginCellEditor extends DefaultCellEditor {
  private final PluginPanel panel;
  private transient PluginNode node;

  protected PluginCellEditor(JComboBox comboBox) {
    super(comboBox);
    panel = new PluginPanel(comboBox);
  }
  @Override public Component getTreeCellEditorComponent(
      JTree tree, Object value, boolean isSelected, boolean expanded,
      boolean leaf, int row) {
    this.node = panel.extractNode(value);
    return panel;
  }
  @Override public Object getCellEditorValue() {
    Object o = super.getCellEditorValue();
    return Optional.ofNullable(node).map(node -> {
      DefaultComboBoxModel m =
        (DefaultComboBoxModel) panel.comboBox.getModel();
      PluginNode n = new PluginNode(panel.pluginName.getText(), node.plugins);
      n.setSelectedPluginIndex(m.getIndexOf(o));
      return (Object) n;
    }).orElse(o);
  }
  @Override public boolean isCellEditable(EventObject e) {
    Object source = e.getSource();
    if (!(source instanceof JTree) || !(e instanceof MouseEvent)) {
      return false;
    }
    JTree tree = (JTree) source;
    Point p = ((MouseEvent) e).getPoint();
    TreePath path = tree.getPathForLocation(p.x, p.y);
    if (Objects.isNull(path)) {
      return false;
    }
    Object node = path.getLastPathComponent();
    if (!(node instanceof DefaultMutableTreeNode)) {
      return false;
    }
    Rectangle r = tree.getPathBounds(path);
    if (Objects.isNull(r)) {
      return false;
    }
    Dimension d = panel.getPreferredSize();
    r.width = d.width;
    if (r.contains(p)) {
      showComboPopup(tree, p);
      return true;
    }
    return delegate.isCellEditable(e);
  }
  private void showComboPopup(JTree tree, Point p) {
    EventQueue.invokeLater(() -> {
      Point pt = SwingUtilities.convertPoint(tree, p, panel);
      Component o = SwingUtilities.getDeepestComponentAt(panel, pt.x, pt.y);
      if (o instanceof JComboBox) {
        panel.comboBox.showPopup();
      } else if (Objects.nonNull(o)) {
        Container c = SwingUtilities.getAncestorOfClass(
            JComboBox.class, (Component) o);
        if (c instanceof JComboBox) {
          panel.comboBox.showPopup();
        }
      }
    });
  }
}

References

2015/06/30

aterai

An Image inside a JScrollPane zooming by mouse wheel and panning by mouse click to drag

Code

class ZoomAndPanePanel extends JPanel {
  private final AffineTransform zoomTransform = new AffineTransform();
  private final transient Image img;
  private final Rectangle imgrect;
  private transient ZoomHandler handler;
  private transient DragScrollListener listener;

  protected ZoomAndPanePanel(Image img) {
    super();
    this.img = img;
    this.imgrect = new Rectangle(img.getWidth(this), img.getHeight(this));
  }
  @Override protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setPaint(new Color(0x55FF0000, true));
    Rectangle r = new Rectangle(500, 140, 150, 150);

    //use: AffineTransform#concatenate(...) and Graphics2D#setTransform(...)
    //https://docs.oracle.com/javase/8/docs/api/java/awt/geom/AffineTransform.html#concatenate-java.awt.geom.AffineTransform-
    //AffineTransform at = g2.getTransform();
    //at.concatenate(zoomTransform);
    //g2.setTransform(at);
    //g2.drawImage(img, 0, 0, this);
    //g2.fill(r);

    //or use: Graphics2D#drawImage(Image, AffineTransform, ImageObserver)
    //https://docs.oracle.com/javase/8/docs/api/java/awt/Graphics2D.html#drawImage-java.awt.Image-java.awt.geom.AffineTransform-java.awt.image.ImageObserver-
    g2.drawImage(img, zoomTransform, this); //or: g2.drawRenderedImage((RenderedImage) img, zoomTransform);
    g2.fill(zoomTransform.createTransformedShape(r));

    //BAD EXAMPLE
    //g2.setTransform(zoomTransform);
    //g2.drawImage(img, 0, 0, this);

    g2.dispose();
  }
  @Override public Dimension getPreferredSize() {
    Rectangle r = zoomTransform.createTransformedShape(imgrect).getBounds();
    return new Dimension(r.width, r.height);
  }
  @Override public void updateUI() {
    removeMouseListener(listener);
    removeMouseMotionListener(listener);
    removeMouseWheelListener(handler);
    super.updateUI();
    listener = new DragScrollListener();
    addMouseListener(listener);
    addMouseMotionListener(listener);
    handler = new ZoomHandler();
    addMouseWheelListener(handler);
  }

  protected class ZoomHandler extends MouseAdapter {
    private static final double ZOOM_MULTIPLICATION_FACTOR = 1.2;
    private static final int MIN_ZOOM = -10;
    private static final int MAX_ZOOM = 10;
    private static final int EXTENT = 1;
    private final BoundedRangeModel zoomRange = new DefaultBoundedRangeModel(
        0, EXTENT, MIN_ZOOM, MAX_ZOOM + EXTENT);
    @Override public void mouseWheelMoved(MouseWheelEvent e) {
      int dir = e.getWheelRotation();
      int z = zoomRange.getValue();
      zoomRange.setValue(z + EXTENT * (dir > 0 ? -1 : 1));
      if (z != zoomRange.getValue()) {
        Component c = e.getComponent();
        Container p = SwingUtilities.getAncestorOfClass(JViewport.class, c);
        if (p instanceof JViewport) {
          JViewport vport = (JViewport) p;
          Rectangle ovr = vport.getViewRect();
          double s = dir > 0 ? 1d / ZOOM_MULTIPLICATION_FACTOR : ZOOM_MULTIPLICATION_FACTOR;
          zoomTransform.scale(s, s);
          //double s = 1d + zoomRange.getValue() * .1;
          //zoomTransform.setToScale(s, s);
          Rectangle nvr = AffineTransform.getScaleInstance(s, s).createTransformedShape(ovr).getBounds();
          Point vp = nvr.getLocation();
          vp.translate((nvr.width - ovr.width) / 2, (nvr.height - ovr.height) / 2);
          vport.setViewPosition(vp);
          c.revalidate();
          c.repaint();
        }
      }
    }
  }
}

References

2014/12/31

aterai

Draggable and sortable JPanels

Code

class RearrangingHandler extends MouseAdapter {
  private static final int xoffset = 16;
  private static final Rectangle R1 = new Rectangle();
  private static final Rectangle R2 = new Rectangle();
  private static Rectangle prevRect;
  private final int gestureMotionThreshold = DragSource.getDragThreshold();
  private final JWindow window = new JWindow();
  private int index = -1;
  private Component draggingComonent;
  private Component gap;
  private Point startPt;
  private Point dragOffset;

  public RearrangingHandler() {
    super();
    window.setBackground(new Color(0, true));
  }
  @Override public void mousePressed(MouseEvent e) {
    if (((JComponent) e.getComponent()).getComponentCount() <= 1) {
      startPt = null;
    } else {
      startPt = e.getPoint();
    }
  }
  private void startDragging(JComponent parent, Point pt) {
    Component c = parent.getComponentAt(pt);
    index = parent.getComponentZOrder(c);
    if (Objects.equals(c, parent) || index < 0) {
      return;
    }
    draggingComonent = c;
    Dimension d = draggingComonent.getSize();

    Point dp = draggingComonent.getLocation();
    dragOffset = new Point(pt.x - dp.x, pt.y - dp.y);

    gap = Box.createRigidArea(d);
    swapComponentLocation(parent, c, gap, index);

    window.add(draggingComonent);
    //window.setSize(d);
    window.pack();

    updateWindowLocation(pt, parent);
    window.setVisible(true);
  }
  private void updateWindowLocation(Point pt, JComponent parent) {
    Point p = new Point(pt.x - dragOffset.x, pt.y - dragOffset.y);
    SwingUtilities.convertPointToScreen(p, parent);
    window.setLocation(p);
  }
  private static int getTargetIndex(Rectangle r, Point pt, int i) {
    int ht2 = (int)(.5 + r.height * .5);
    R1.setBounds(r.x, r.y,       r.width, ht2);
    R2.setBounds(r.x, r.y + ht2, r.width, ht2);
    if (R1.contains(pt)) {
      prevRect = R1;
      return i - 1 > 0 ? i : 0;
    } else if (R2.contains(pt)) {
      prevRect = R2;
      return i;
    }
    return -1;
  }
  private static void swapComponentLocation(
      Container parent, Component remove, Component add, int idx) {
    parent.remove(remove);
    parent.add(add, idx);
    parent.revalidate();
    parent.repaint();
  }
  @Override public void mouseDragged(MouseEvent e) {
    Point pt = e.getPoint();
    JComponent parent = (JComponent) e.getComponent();
    double a = Math.pow(pt.x - startPt.x, 2);
    double b = Math.pow(pt.y - startPt.y, 2);
    if (draggingComonent == null &&
        Math.sqrt(a + b) > gestureMotionThreshold) {
      startDragging(parent, pt);
      return;
    }
    if (!window.isVisible() || draggingComonent == null) {
      return;
    }
    updateWindowLocation(pt, parent);
    if (prevRect != null && prevRect.contains(pt)) {
      return;
    }

    for (int i = 0; i < parent.getComponentCount(); i++) {
      Component c = parent.getComponent(i);
      Rectangle r = c.getBounds();
      if (Objects.equals(c, gap) && r.contains(pt)) {
        return;
      }
      int tgt = getTargetIndex(r, pt, i);
      if (tgt >= 0) {
        swapComponentLocation(parent, gap, gap, tgt);
        return;
      }
    }
    //System.out.println("outer");
    parent.remove(gap);
    parent.revalidate();
  }

  @Override public void mouseReleased(MouseEvent e) {
    startPt = null;
    if (!window.isVisible() || draggingComonent == null) {
      return;
    }
    Point pt = e.getPoint();
    JComponent parent = (JComponent) e.getComponent();

    Component cmp = draggingComonent;
    draggingComonent = null;
    prevRect = null;
    startPt = null;
    dragOffset = null;
    window.setVisible(false);

    for (int i = 0; i < parent.getComponentCount(); i++) {
      Component c = parent.getComponent(i);
      if (Objects.equals(c, gap)) {
        swapComponentLocation(parent, gap, cmp, i);
        return;
      }
      int tgt = getTargetIndex(c.getBounds(), pt, i);
      if (tgt >= 0) {
        swapComponentLocation(parent, gap, cmp, tgt);
        return;
      }
    }
    if (parent.getParent().getBounds().contains(pt)) {
      swapComponentLocation(parent, gap, cmp, parent.getComponentCount());
    } else {
      swapComponentLocation(parent, gap, cmp, index);
    }
  }
}

References

2014/02/26

aterai

Translucent JFrame repaint

Code

private final SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
private final JLabel label = new JLabel(df.format(new Date()), SwingConstants.CENTER);
private final TexturePanel tp;
private final Timer timer = new Timer(1000, new ActionListener() {
  @Override public void actionPerformed(ActionEvent e) {
    label.setText(df.format(new Date()));
    Container parent = SwingUtilities.getUnwrappedParent(label);
    if (parent != null && parent.isOpaque()) {
      repaintWindowAncestor(label);
    }
  }
});
private final JToggleButton button = new JToggleButton(new AbstractAction("timer") {
  private JFrame digitalClock;
  @Override public void actionPerformed(ActionEvent e) {
    if (digitalClock == null) {
      digitalClock = new JFrame();
      digitalClock.setUndecorated(true);
      digitalClock.setBackground(new Color(0, 0, 0, 0));
      digitalClock.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
      digitalClock.getContentPane().add(tp);
      digitalClock.pack();
      digitalClock.setLocationRelativeTo(null);
    }
    if (((AbstractButton) e.getSource()).isSelected()) {
      TexturePaints t = (TexturePaints) combo.getSelectedItem();
      tp.setTexturePaint(t.getTexturePaint());
      timer.start();
      digitalClock.setVisible(true);
    } else {
      timer.stop();
      digitalClock.setVisible(false);
    }
  }
});
private void repaintWindowAncestor(JComponent c) {
  JRootPane root = c.getRootPane();
  if (root == null) {
    return;
  }
  Rectangle r = SwingUtilities.convertRectangle(c, c.getBounds(), root);
  root.repaint(r.x, r.y, r.width, r.height);
}

References

2013/12/09

aterai

Breadcrumb Navigation with JRadioButton

Code

private static JComponent makeBreadcrumbList(int overlap, List< String> list) {
  JPanel p = new JPanel(new FlowLayout(FlowLayout.LEADING, -overlap, 0));
  p.setBorder(BorderFactory.createEmptyBorder(4, overlap+4, 4, 4));
  p.setOpaque(false);
  ButtonGroup bg = new ButtonGroup();
  for(String title: list) {
    AbstractButton b = makeButton(title, Color.PINK);
    p.add(b);
    bg.add(b);
  }
  return p;
}

References

2012/05/25

aterai

Creating a Custom Layout Manager

Code

final double A2 = 4.0;
panel2.setLayout(new FlowLayout() {
  @Override public void layoutContainer(Container target) {
    synchronized(target.getTreeLock()) {
      Insets insets = target.getInsets();
      int nmembers  = target.getComponentCount();
      if(nmembers<=0) return;
      int vgap = getVgap();
      int hgap = getHgap();
      int rowh = (target.getHeight()-(insets.top+insets.bottom+vgap*2))/nmembers;
      int x = insets.left + hgap;
      int y = insets.top  + vgap;
      for(int i=0;i < nmembers; i++) {
        Component m = target.getComponent(i);
        if(m.isVisible()) {
          Dimension d = m.getPreferredSize();
          m.setSize(d.width, d.height);
          m.setLocation(x, y);
          y += (vgap + Math.min(rowh, d.height));
          x = (int)(A2 * Math.sqrt(y));
        }
      }
    }
  }
});

References

2011/03/10

aterai

CheckBoxes in JTable Cell

Code

class CheckBoxesPanel extends JPanel {
  protected final String[] title = {"r", "w", "x"};
  public JCheckBox[] buttons;
  public CheckBoxesPanel() {
    super();
    setOpaque(false);
    setBackground(new Color(0,0,0,0));
    setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
    initButtons();
  }
  protected void initButtons() {
    buttons = new JCheckBox[title.length];
    for(int i=0; i < buttons.length; i++) {
      JCheckBox b = new JCheckBox(title[i]);
      b.setOpaque(false);
      b.setFocusable(false);
      b.setRolloverEnabled(false);
      b.setBackground(new Color(0,0,0,0));
      buttons[i] = b;
      add(b);
      add(Box.createHorizontalStrut(5));
    }
  }
  protected void updateButtons(Object v) {
    if("Windows 7".equals(OSNAME)) { //Windows aero?
      removeAll();
      initButtons();
    }
    Integer i = (Integer)(v==null?0:v);
    buttons[0].setSelected((i&(1<<2))!=0);
    buttons[1].setSelected((i&(1<<1))!=0);
    buttons[2].setSelected((i&(1<<0))!=0);
  }
}
class CheckBoxesRenderer extends CheckBoxesPanel
                         implements TableCellRenderer, Serializable {
  public CheckBoxesRenderer() {
    super();
    setName("Table.cellRenderer");
  }
  @Override public Component getTableCellRendererComponent(JTable table,
      Object value, boolean isSelected, boolean hasFocus, int row, int column) {
    updateButtons(value);
    return this;
  }
  public static class UIResource extends CheckBoxesRenderer
                                 implements UIResource{}
}
class CheckBoxesEditor extends CheckBoxesPanel
                       implements TableCellEditor, Serializable {
  public CheckBoxesEditor() {
    ActionListener al = new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        fireEditingStopped();
      }
    };
    ActionMap am = getActionMap();
    for(int i=0; i < buttons.length; i++) {
      final JCheckBox b = buttons[i];
      b.addActionListener(al);
      am.put(title[i], new AbstractAction(title[i]) {
        public void actionPerformed(ActionEvent e) {
          b.setSelected(!b.isSelected());
          fireEditingStopped();
        }
      });
    }
    InputMap im = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_R, 0), title[0]);
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), title[1]);
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, 0), title[2]);
  }
  @Override public Component getTableCellEditorComponent(JTable table,
        Object value, boolean isSelected, int row, int column) {
    updateButtons(value);
    return this;
  }
  @Override public Object getCellEditorValue() {
    int i = 0;
    if(buttons[0].isSelected()) i|=1<<2;
    if(buttons[1].isSelected()) i|=1<<1;
    if(buttons[2].isSelected()) i|=1<<0;
    return i;
  }

  //Copid from AbstractCellEditor
  protected EventListenerList listenerList = new EventListenerList();
  transient protected ChangeEvent changeEvent = null;
  //......

References

2010/05/10

aterai

Custom Decorated TitleBar JFrame

Code

class ResizeWindowListener extends MouseAdapter {
  private Rectangle startSide = null;
  private final JFrame frame;
  public ResizeWindowListener(JFrame frame) {
    this.frame = frame;
  }
  public void mousePressed(MouseEvent e) {
    startSide = frame.getBounds();
  }
  public void mouseDragged(MouseEvent e) {
    if(startSide==null) return;
    Component c = e.getComponent();
    if(c==topleft) {
      startSide.y += e.getY();
      startSide.height -= e.getY();
      startSide.x += e.getX();
      startSide.width -= e.getX();
    }else if(c==top) {
      startSide.y += e.getY();
      startSide.height -= e.getY();
    }else if(c==topright) {
      startSide.y += e.getY();
      startSide.height -= e.getY();
      startSide.width += e.getX();
    }else if(c==left) {
      startSide.x += e.getX();
      startSide.width -= e.getX();
    }else if(c==right) {
      startSide.width += e.getX();
    }else if(c==bottomleft) {
      startSide.height += e.getY();
      startSide.x += e.getX();
      startSide.width -= e.getX();
    }else if(c==bottom) {
      startSide.height += e.getY();
    }else if(c==bottomright) {
      startSide.height += e.getY();
      startSide.width += e.getX();
    }
    frame.setBounds(startSide);
  }
}

References

2009/10/06

aterai

Multiple JButtons in a JTable cell

Code

class ButtonsPanel extends JPanel {
  public final List buttons =
    Arrays.asList(new JButton("view"), new JButton("edit"));
  public ButtonsPanel() {
    super();
    setOpaque(true);
    for(JButton b: buttons) {
      b.setFocusable(false);
      b.setRolloverEnabled(false);
      add(b);
    }
  }
}
class ButtonsRenderer extends ButtonsPanel
                      implements TableCellRenderer {
  public ButtonsRenderer() {
    super();
    setName("Table.cellRenderer");
  }
  @Override public Component getTableCellRendererComponent(JTable table,
        Object value, boolean isSelected, boolean hasFocus, int row, int column) {
    setBackground(isSelected?table.getSelectionBackground():table.getBackground());
    return this;
  }
}
class ButtonsEditor extends ButtonsPanel
                    implements TableCellEditor {
  public ButtonsEditor(final JTable table) {
    super();
    //---->
    //DEBUG: view button click -> control key down + edit button(same cell) press
    //       -> remain selection color
    MouseListener ml = new MouseAdapter() {
      public void mousePressed(MouseEvent e) {
        ButtonModel m = ((JButton)e.getSource()).getModel();
        if(m.isPressed() && table.isRowSelected(table.getEditingRow())
                         && e.isControlDown()) {
          setBackground(table.getBackground());
        }
      }
    };
    buttons.get(0).addMouseListener(ml);
    buttons.get(1).addMouseListener(ml);
    //<----

    buttons.get(0).addActionListener(new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        fireEditingStopped();
        JOptionPane.showMessageDialog(table, "Viewing");
      }
    });

    buttons.get(1).addActionListener(new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        int row = table.convertRowIndexToModel(table.getEditingRow());
        Object o = table.getModel().getValueAt(row, 0);
        fireEditingStopped();
        JOptionPane.showMessageDialog(table, "Editing: "+o);
      }
    });

    addMouseListener(new MouseAdapter() {
      @Override public void mousePressed(MouseEvent e) {
        fireEditingStopped();
      }
    });
  }
  @Override public Component getTableCellEditorComponent(JTable table,
        Object value, boolean isSelected, int row, int column) {
    this.setBackground(table.getSelectionBackground());
    return this;
  }
  @Override public Object getCellEditorValue() {
    return "";
  }
  //Copid from AbstractCellEditor
  //protected EventListenerList listenerList = new EventListenerList();
  transient protected ChangeEvent changeEvent = null;
  @Override public boolean isCellEditable(java.util.EventObject e) {
    return true;
  }
//......

References

2008/08/13

aterai

Multi Column JComboBox

Code

class MultiColumnCellRenderer extends JPanel implements ListCellRenderer{
  private final JLabel leftLabel = new JLabel();
  private final JLabel rightLabel;
  public MultiColumnCellRenderer(int rightWidth) {
    super(new BorderLayout());
    this.setBorder(BorderFactory.createEmptyBorder(1,1,1,1));

    leftLabel.setOpaque(false);
    leftLabel.setBorder(BorderFactory.createEmptyBorder(0,2,0,0));

    final Dimension dim = new Dimension(rightWidth, 0);
    rightLabel = new JLabel() {
      @Override public Dimension getPreferredSize() {
        return dim;
      }
    };
    rightLabel.setOpaque(false);
    rightLabel.setBorder(BorderFactory.createEmptyBorder(0,2,0,2));
    rightLabel.setForeground(Color.GRAY);
    rightLabel.setHorizontalAlignment(SwingConstants.RIGHT);

    this.add(leftLabel);
    this.add(rightLabel, BorderLayout.EAST);
  }
  @Override public Component getListCellRendererComponent(
      JList list, Object value, int index,
      boolean isSelected, boolean cellHasFocus) {
    LRItem item = (LRItem)value;
    leftLabel.setText(item.getLeftText());
    rightLabel.setText(item.getRightText());

    leftLabel.setFont(list.getFont());
    rightLabel.setFont(list.getFont());

    if(index<0) {
      leftLabel.setForeground(list.getForeground());
      this.setOpaque(false);
    }else{
      leftLabel.setForeground(
          isSelected?list.getSelectionForeground():list.getForeground());
      this.setBackground(
          isSelected?list.getSelectionBackground():list.getBackground());
      this.setOpaque(true);
    }
    return this;
  }
  @Override public Dimension getPreferredSize() {
    Dimension d = super.getPreferredSize();
    return new Dimension(0, d.height);
  }
  @Override public void updateUI() {
    super.updateUI();
    this.setName("List.cellRenderer");
  }
}

References