From 218de052e0693a8b857f13c816b410467fafd838 Mon Sep 17 00:00:00 2001 From: Cody Date: Mon, 23 Jan 2023 22:43:48 -0800 Subject: [PATCH 1/2] Enabled tabs to be rearranged. Did not add functionality for a tab to be dropped out. We could possibly add it at a later time, also add a setting to toggle it on/off? Recommend to gather feedback to see if that is something wanted. --- .../club/bytecodeviewer/BytecodeViewer.java | 2 +- .../resourceviewer/CloseButtonComponent.java | 39 ++ .../resourceviewer/DraggableTabbedPane.java | 613 ++++++++++++++++++ .../gui/resourceviewer/TabExitButton.java | 34 +- .../gui/resourceviewer/TabbedPane.java | 343 +++++----- .../gui/resourceviewer/Workspace.java | 68 +- 6 files changed, 881 insertions(+), 218 deletions(-) create mode 100644 src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/CloseButtonComponent.java create mode 100644 src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/DraggableTabbedPane.java diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/BytecodeViewer.java b/src/main/java/the/bytecode/club/bytecodeviewer/BytecodeViewer.java index 4210f384..7126ea9a 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/BytecodeViewer.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/BytecodeViewer.java @@ -130,7 +130,7 @@ import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory; public class BytecodeViewer { //TODO fix this for tab dragging & better tab controls - public static boolean EXPERIMENTAL_TAB_CODE = false; + public static boolean EXPERIMENTAL_TAB_CODE = true; //the launch args called on BCV public static String[] launchArgs; diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/CloseButtonComponent.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/CloseButtonComponent.java new file mode 100644 index 00000000..277834b8 --- /dev/null +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/CloseButtonComponent.java @@ -0,0 +1,39 @@ +package the.bytecode.club.bytecodeviewer.gui.resourceviewer; + +import com.android.tools.r8.internal.Cl; +import com.github.weisj.darklaf.components.CloseButton; + +import javax.swing.*; +import java.awt.*; + +public class CloseButtonComponent extends JPanel { + + private final JTabbedPane pane; + + public CloseButtonComponent(final JTabbedPane pane) { + super(new FlowLayout(FlowLayout.LEFT, 0, 0)); + if (pane == null) { + throw new NullPointerException("TabbedPane is null"); + } + + this.pane = pane; + setOpaque(false); + JLabel label = new JLabel() { + public String getText() { + int i = pane.indexOfTabComponent(CloseButtonComponent.this); + if (i != -1) { + return pane.getTitleAt(i); + } + + return null; + } + }; + + add(label); + label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5)); + JButton button = new CloseButton(); + add(button); + setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0)); + } + +} diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/DraggableTabbedPane.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/DraggableTabbedPane.java new file mode 100644 index 00000000..3afcbfd8 --- /dev/null +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/DraggableTabbedPane.java @@ -0,0 +1,613 @@ +package the.bytecode.club.bytecodeviewer.gui.resourceviewer; + +import com.github.weisj.darklaf.components.CloseButton; +import the.bytecode.club.bytecodeviewer.BytecodeViewer; + +import javax.swing.*; +import java.awt.*; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.dnd.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionAdapter; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; + +public class DraggableTabbedPane extends JTabbedPane { + + public static final long serialVersionUID = 1L; + private static final int LINEWIDTH = 3; + private static final String NAME = "TabTransferData"; + private final DataFlavor FLAVOR = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType, NAME); + private static GhostGlassPane s_glassPane = new GhostGlassPane(); + + private boolean m_isDrawRect = false; + private final Rectangle2D m_lineRect = new Rectangle2D.Double(); + + private final Color m_lineColor = new Color(0, 100, 255); + private TabAcceptor m_acceptor = null; + + public DraggableTabbedPane() { + super(SwingConstants.TOP, SCROLL_TAB_LAYOUT); + + final DragSourceListener dsl = new DragSourceListener() { + public void dragEnter(DragSourceDragEvent e) { + e.getDragSourceContext().setCursor(DragSource.DefaultMoveDrop); + } + + public void dragExit(DragSourceEvent e) { + e.getDragSourceContext().setCursor(DragSource.DefaultMoveNoDrop); + m_lineRect.setRect(0, 0, 0, 0); + m_isDrawRect = false; + s_glassPane.setPoint(new Point(-1000, -1000)); + s_glassPane.repaint(); + } + + public void dragOver(DragSourceDragEvent e) { + //e.getLocation() + //This method returns a Point indicating the cursor location in screen coordinates at the moment + + TabTransferData data = getTabTransferData(e); + if (data == null) { + e.getDragSourceContext().setCursor( + DragSource.DefaultMoveNoDrop); + return; + } // if + + /* + Point tabPt = e.getLocation(); + SwingUtilities.convertPointFromScreen(tabPt, DnDTabbedPane.this); + if (DnDTabbedPane.this.contains(tabPt)) { + int targetIdx = getTargetTabIndex(tabPt); + int sourceIndex = data.getTabIndex(); + if (getTabAreaBound().contains(tabPt) + && (targetIdx >= 0) + && (targetIdx != sourceIndex) + && (targetIdx != sourceIndex + 1)) { + e.getDragSourceContext().setCursor( + DragSource.DefaultMoveDrop); + + return; + } // if + + e.getDragSourceContext().setCursor( + DragSource.DefaultMoveNoDrop); + return; + } // if + */ + + e.getDragSourceContext().setCursor( + DragSource.DefaultMoveDrop); + } + + public void dragDropEnd(DragSourceDropEvent e) { + m_isDrawRect = false; + m_lineRect.setRect(0, 0, 0, 0); + // m_dragTabIndex = -1; + + if (hasGhost()) { + s_glassPane.setVisible(false); + s_glassPane.setImage(null); + } + } + + public void dropActionChanged(DragSourceDragEvent e) { + } + }; + + final DragGestureListener dgl = e -> { + // System.out.println("dragGestureRecognized"); + + Point tabPt = e.getDragOrigin(); + int dragTabIndex = indexAtLocation(tabPt.x, tabPt.y); + if (dragTabIndex < 0) { + return; + } // if + + initGlassPane(e.getComponent(), e.getDragOrigin(), dragTabIndex); + try { + e.startDrag(DragSource.DefaultMoveDrop, + new TabTransferable(DraggableTabbedPane.this, dragTabIndex), dsl); + } catch (InvalidDnDOperationException idoe) { + idoe.printStackTrace(); + } + }; + + //dropTarget = + new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, + new CDropTargetListener(), true); + new DragSource().createDefaultDragGestureRecognizer(this, + DnDConstants.ACTION_COPY_OR_MOVE, dgl); + m_acceptor = (a_component, a_index) -> true; + } + + public TabAcceptor getAcceptor() { + return m_acceptor; + } + + public void setAcceptor(TabAcceptor a_value) { + m_acceptor = a_value; + } + + private TabTransferData getTabTransferData(DropTargetDropEvent a_event) { + try { + return (TabTransferData) a_event.getTransferable().getTransferData(FLAVOR); + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + private TabTransferData getTabTransferData(DropTargetDragEvent a_event) { + try { + return (TabTransferData) a_event.getTransferable().getTransferData(FLAVOR); + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + private TabTransferData getTabTransferData(DragSourceDragEvent a_event) { + try { + return (TabTransferData) a_event.getDragSourceContext().getTransferable().getTransferData(FLAVOR); + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + class TabTransferable implements Transferable { + + private TabTransferData m_data = null; + + public TabTransferable(DraggableTabbedPane a_tabbedPane, int a_tabIndex) { + m_data = new TabTransferData(a_tabbedPane, a_tabIndex); + } + + public Object getTransferData(DataFlavor flavor) { + return m_data; + // return DnDTabbedPane.this; + } + + public DataFlavor[] getTransferDataFlavors() { + DataFlavor[] f = new DataFlavor[1]; + f[0] = FLAVOR; + return f; + } + + public boolean isDataFlavorSupported(DataFlavor flavor) { + return flavor.getHumanPresentableName().equals(NAME); + } + } + + static class TabTransferData { + + private DraggableTabbedPane m_tabbedPane = null; + private int m_tabIndex = -1; + + public TabTransferData() { + } + + public TabTransferData(DraggableTabbedPane a_tabbedPane, int a_tabIndex) { + m_tabbedPane = a_tabbedPane; + m_tabIndex = a_tabIndex; + } + + public DraggableTabbedPane getTabbedPane() { + return m_tabbedPane; + } + + public void setTabbedPane(DraggableTabbedPane pane) { + m_tabbedPane = pane; + } + + public int getTabIndex() { + return m_tabIndex; + } + + public void setTabIndex(int index) { + m_tabIndex = index; + } + } + + private Point buildGhostLocation(Point a_location) { + Point retval = new Point(a_location); + + switch (getTabPlacement()) { + case JTabbedPane.TOP: { + retval.y = 1; + retval.x -= s_glassPane.getGhostWidth() / 2; + } + break; + + case JTabbedPane.BOTTOM: { + retval.y = getHeight() - 1 - s_glassPane.getGhostHeight(); + retval.x -= s_glassPane.getGhostWidth() / 2; + } + break; + + case JTabbedPane.LEFT: { + retval.x = 1; + retval.y -= s_glassPane.getGhostHeight() / 2; + } + break; + + case JTabbedPane.RIGHT: { + retval.x = getWidth() - 1 - s_glassPane.getGhostWidth(); + retval.y -= s_glassPane.getGhostHeight() / 2; + } + break; + } // switch + + retval = SwingUtilities.convertPoint(DraggableTabbedPane.this, + retval, s_glassPane); + return retval; + } + + class CDropTargetListener implements DropTargetListener { + + public void dragEnter(DropTargetDragEvent e) { + // System.out.println("DropTarget.dragEnter: " + DnDTabbedPane.this); + + if (isDragAcceptable(e)) { + e.acceptDrag(e.getDropAction()); + } else { + e.rejectDrag(); + } // if + } + + public void dragExit(DropTargetEvent e) { + // System.out.println("DropTarget.dragExit: " + DnDTabbedPane.this); + m_isDrawRect = false; + } + + public void dropActionChanged(DropTargetDragEvent e) { + } + + public void dragOver(final DropTargetDragEvent e) { + TabTransferData data = getTabTransferData(e); + + if (getTabPlacement() == JTabbedPane.TOP + || getTabPlacement() == JTabbedPane.BOTTOM) { + initTargetLeftRightLine(getTargetTabIndex(e.getLocation()), data); + } else { + initTargetTopBottomLine(getTargetTabIndex(e.getLocation()), data); + } // if-else + + repaint(); + if (hasGhost()) { + s_glassPane.setPoint(buildGhostLocation(e.getLocation())); + s_glassPane.repaint(); + } + } + + public void drop(DropTargetDropEvent a_event) { + // System.out.println("DropTarget.drop: " + DnDTabbedPane.this); + + if (isDropAcceptable(a_event)) { + convertTab(getTabTransferData(a_event), getTargetTabIndex(a_event.getLocation())); + a_event.dropComplete(true); + } else { + a_event.dropComplete(false); + } // if-else + + m_isDrawRect = false; + repaint(); + + BytecodeViewer.viewer.workPane.tabs.setTabComponentAt(getSelectedIndex(), new CloseButtonComponent(DraggableTabbedPane.this)); + } + + public boolean isDragAcceptable(DropTargetDragEvent e) { + Transferable t = e.getTransferable(); + if (t == null) { + return false; + } // if + + DataFlavor[] flavor = e.getCurrentDataFlavors(); + if (!t.isDataFlavorSupported(flavor[0])) { + return false; + } // if + + TabTransferData data = getTabTransferData(e); + + if (DraggableTabbedPane.this == data.getTabbedPane() + && data.getTabIndex() >= 0) { + return true; + } // if + + if (DraggableTabbedPane.this != data.getTabbedPane()) { + if (m_acceptor != null) { + return m_acceptor.isDropAcceptable(data.getTabbedPane(), data.getTabIndex()); + } // if + } // if + + return false; + } + + public boolean isDropAcceptable(DropTargetDropEvent e) { + Transferable t = e.getTransferable(); + if (t == null) { + return false; + } // if + + DataFlavor[] flavor = e.getCurrentDataFlavors(); + if (!t.isDataFlavorSupported(flavor[0])) { + return false; + } // if + + TabTransferData data = getTabTransferData(e); + + if (DraggableTabbedPane.this == data.getTabbedPane() + && data.getTabIndex() >= 0) { + return true; + } // if + + if (DraggableTabbedPane.this != data.getTabbedPane()) { + if (m_acceptor != null) { + return m_acceptor.isDropAcceptable(data.getTabbedPane(), data.getTabIndex()); + } // if + } // if + + return false; + } + } + + private boolean m_hasGhost = true; + + public void setPaintGhost(boolean flag) { + m_hasGhost = flag; + } + + public boolean hasGhost() { + return m_hasGhost; + } + + /** + * returns potential index for drop. + * + * @param a_point point given in the drop site component's coordinate + * @return returns potential index for drop. + */ + private int getTargetTabIndex(Point a_point) { + boolean isTopOrBottom = getTabPlacement() == JTabbedPane.TOP + || getTabPlacement() == JTabbedPane.BOTTOM; + + // if the pane is empty, the target index is always zero. + if (getTabCount() == 0) { + return 0; + } // if + + for (int i = 0; i < getTabCount(); i++) { + Rectangle r = getBoundsAt(i); + if (isTopOrBottom) { + r.setRect(r.x - r.width / 2, r.y, r.width, r.height); + } else { + r.setRect(r.x, r.y - r.height / 2, r.width, r.height); + } // if-else + + if (r.contains(a_point)) { + return i; + } // if + } // for + + Rectangle r = getBoundsAt(getTabCount() - 1); + if (isTopOrBottom) { + int x = r.x + r.width / 2; + r.setRect(x, r.y, getWidth() - x, r.height); + } else { + int y = r.y + r.height / 2; + r.setRect(r.x, y, r.width, getHeight() - y); + } // if-else + + return r.contains(a_point) ? getTabCount() : -1; + } + + private void convertTab(TabTransferData a_data, int a_targetIndex) { + DraggableTabbedPane source = a_data.getTabbedPane(); + int sourceIndex = a_data.getTabIndex(); + if (sourceIndex < 0) { + return; + } // if + + Component cmp = source.getComponentAt(sourceIndex); + String str = source.getTitleAt(sourceIndex); + if (this != source) { + source.remove(sourceIndex); + + if (a_targetIndex == getTabCount()) { + addTab(str, cmp); + } else { + if (a_targetIndex < 0) { + a_targetIndex = 0; + } // if + + insertTab(str, null, cmp, null, a_targetIndex); + + } // if + + setSelectedComponent(cmp); + // System.out.println("press="+sourceIndex+" next="+a_targetIndex); + return; + } // if + + if (a_targetIndex < 0 || sourceIndex == a_targetIndex) { + //System.out.println("press="+prev+" next="+next); + return; + } // if + + if (a_targetIndex == getTabCount()) { + //System.out.println("last: press="+prev+" next="+next); + source.remove(sourceIndex); + addTab(str, cmp); + setSelectedIndex(getTabCount() - 1); + } else if (sourceIndex > a_targetIndex) { + //System.out.println(" >: press="+prev+" next="+next); + source.remove(sourceIndex); + insertTab(str, null, cmp, null, a_targetIndex); + setSelectedIndex(a_targetIndex); + } else { + //System.out.println(" <: press="+prev+" next="+next); + source.remove(sourceIndex); + insertTab(str, null, cmp, null, a_targetIndex - 1); + setSelectedIndex(a_targetIndex - 1); + } + } + + private void initTargetLeftRightLine(int next, TabTransferData a_data) { + if (next < 0) { + m_lineRect.setRect(0, 0, 0, 0); + m_isDrawRect = false; + return; + } // if + + if ((a_data.getTabbedPane() == this) + && (a_data.getTabIndex() == next + || next - a_data.getTabIndex() == 1)) { + m_lineRect.setRect(0, 0, 0, 0); + m_isDrawRect = false; + } else if (getTabCount() == 0) { + m_lineRect.setRect(0, 0, 0, 0); + m_isDrawRect = false; + return; + } else if (next == 0) { + Rectangle rect = getBoundsAt(0); + m_lineRect.setRect(-LINEWIDTH / 2, rect.y, LINEWIDTH, rect.height); + m_isDrawRect = true; + } else if (next == getTabCount()) { + Rectangle rect = getBoundsAt(getTabCount() - 1); + m_lineRect.setRect(rect.x + rect.width - LINEWIDTH / 2, rect.y, + LINEWIDTH, rect.height); + m_isDrawRect = true; + } else { + Rectangle rect = getBoundsAt(next - 1); + m_lineRect.setRect(rect.x + rect.width - LINEWIDTH / 2, rect.y, + LINEWIDTH, rect.height); + m_isDrawRect = true; + } + } + + private void initTargetTopBottomLine(int next, TabTransferData a_data) { + if (next < 0) { + m_lineRect.setRect(0, 0, 0, 0); + m_isDrawRect = false; + return; + } // if + + if ((a_data.getTabbedPane() == this) + && (a_data.getTabIndex() == next + || next - a_data.getTabIndex() == 1)) { + m_lineRect.setRect(0, 0, 0, 0); + m_isDrawRect = false; + } else if (getTabCount() == 0) { + m_lineRect.setRect(0, 0, 0, 0); + m_isDrawRect = false; + return; + } else if (next == getTabCount()) { + Rectangle rect = getBoundsAt(getTabCount() - 1); + m_lineRect.setRect(rect.x, rect.y + rect.height - LINEWIDTH / 2, + rect.width, LINEWIDTH); + m_isDrawRect = true; + } else if (next == 0) { + Rectangle rect = getBoundsAt(0); + m_lineRect.setRect(rect.x, -LINEWIDTH / 2, rect.width, LINEWIDTH); + m_isDrawRect = true; + } else { + Rectangle rect = getBoundsAt(next - 1); + m_lineRect.setRect(rect.x, rect.y + rect.height - LINEWIDTH / 2, + rect.width, LINEWIDTH); + m_isDrawRect = true; + } + } + + private void initGlassPane(Component c, Point tabPt, int a_tabIndex) { + //Point p = (Point) pt.clone(); + getRootPane().setGlassPane(s_glassPane); + if (hasGhost()) { + Rectangle rect = getBoundsAt(a_tabIndex); + BufferedImage image = new BufferedImage(c.getWidth(), + c.getHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics g = image.getGraphics(); + c.paint(g); + image = image.getSubimage(rect.x, rect.y, rect.width, rect.height); + s_glassPane.setImage(image); + } // if + + s_glassPane.setPoint(buildGhostLocation(tabPt)); + s_glassPane.setVisible(true); + } + + private Rectangle getTabAreaBound() { + Rectangle lastTab = getUI().getTabBounds(this, getTabCount() - 1); + return new Rectangle(0, 0, getWidth(), lastTab.y + lastTab.height); + } + + public void paintComponent(Graphics g) { + super.paintComponent(g); + + if (m_isDrawRect) { + Graphics2D g2 = (Graphics2D) g; + g2.setPaint(m_lineColor); + g2.fill(m_lineRect); + } // if + } + + public interface TabAcceptor { + + boolean isDropAcceptable(DraggableTabbedPane a_component, int a_index); + } +} + +class GhostGlassPane extends JPanel { + + public static final long serialVersionUID = 1L; + private final AlphaComposite m_composite; + + private Point m_location = new Point(0, 0); + + private BufferedImage m_draggingGhost = null; + + public GhostGlassPane() { + setOpaque(false); + m_composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f); + } + + public void setImage(BufferedImage draggingGhost) { + m_draggingGhost = draggingGhost; + } + + public void setPoint(Point a_location) { + m_location.x = a_location.x; + m_location.y = a_location.y; + } + + public int getGhostWidth() { + if (m_draggingGhost == null) { + return 0; + } // if + + return m_draggingGhost.getWidth(this); + } + + public int getGhostHeight() { + if (m_draggingGhost == null) { + return 0; + } // if + + return m_draggingGhost.getHeight(this); + } + + public void paintComponent(Graphics g) { + if (m_draggingGhost == null) { + return; + } // if + + Graphics2D g2 = (Graphics2D) g; + g2.setComposite(m_composite); + g2.drawImage(m_draggingGhost, (int) m_location.getX(), (int) m_location.getY(), null); + } +} diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/TabExitButton.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/TabExitButton.java index 75ca650b..07828705 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/TabExitButton.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/TabExitButton.java @@ -35,14 +35,13 @@ import javax.swing.plaf.basic.BasicButtonUI; * Using CloseButton of darklaf instead. 4/17/2022 */ @Deprecated -public class TabExitButton extends JButton implements ActionListener -{ +public class TabExitButton extends JButton implements ActionListener { + private final TabbedPane tabbedPane; private final int tabIndex; private final String tabWorkingName; - public TabExitButton(TabbedPane tabbedPane, int tabIndex, String tabWorkingName) - { + public TabExitButton(TabbedPane tabbedPane, int tabIndex, String tabWorkingName) { this.tabbedPane = tabbedPane; this.tabIndex = tabIndex; this.tabWorkingName = tabWorkingName; @@ -65,29 +64,26 @@ public class TabExitButton extends JButton implements ActionListener addActionListener(this); } - public int getTabIndex() - { + public int getTabIndex() { return tabIndex; } @Override - public void actionPerformed(final ActionEvent e) - { + public void actionPerformed(final ActionEvent e) { final int i = tabbedPane.tabs.indexOfTabComponent(tabbedPane); - if (i != -1) - { + if (i != -1) { tabbedPane.tabs.remove(i); } } // we don't want to update UI for this button @Override - public void updateUI() { } + public void updateUI() { + } // paint the cross @Override - protected void paintComponent(final Graphics g) - { + protected void paintComponent(final Graphics g) { super.paintComponent(g); final Graphics2D g2 = (Graphics2D) g.create(); // shift the image for pressed buttons @@ -97,8 +93,9 @@ public class TabExitButton extends JButton implements ActionListener g2.setStroke(new BasicStroke(2)); g2.setColor(Color.BLACK); - if (getModel().isRollover()) + if (getModel().isRollover()) { g2.setColor(Color.MAGENTA); + } final int delta = 6; g2.drawLine(delta, delta, getWidth() - delta - 1, getHeight() - delta - 1); @@ -106,18 +103,15 @@ public class TabExitButton extends JButton implements ActionListener g2.dispose(); } - public TabbedPane getTabbedPane() - { + public TabbedPane getTabbedPane() { return tabbedPane; } - public String getTabWorkingName() - { + public String getTabWorkingName() { return tabWorkingName; } - public static long getSerialVersionUID() - { + public static long getSerialVersionUID() { return serialVersionUID; } diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/TabbedPane.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/TabbedPane.java index d054c8ff..4f491e09 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/TabbedPane.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/TabbedPane.java @@ -7,14 +7,7 @@ import java.awt.Rectangle; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JTabbedPane; -import javax.swing.SwingUtilities; +import javax.swing.*; import com.github.weisj.darklaf.components.CloseButton; import the.bytecode.club.bytecodeviewer.BytecodeViewer; @@ -50,85 +43,82 @@ import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings; * @author WaterWolf * @since 09/26/2011 */ -public class TabbedPane extends JPanel -{ - public final JTabbedPane tabs; - public final JLabel label; - private DelayTabbedPaneThread probablyABadIdea; - private long startedDragging = 0; - public final String tabName; - public final String fileContainerName; - public final ResourceViewer resource; - private static long lastMouseClick = System.currentTimeMillis(); - public final static MouseListener buttonHoverAnimation = new ButtonHoverAnimation(); - public static final Color BLANK_COLOR = new Color(0, 0, 0, 0); - - public TabbedPane(int tabIndex, String tabWorkingName, String fileContainerName, String name, final JTabbedPane existingTabs, ResourceViewer resource) - { - // unset default FlowLayout' gaps - super(new FlowLayout(FlowLayout.LEFT, 0, 0)); +public class TabbedPane extends JPanel { - this.tabName = name; - this.fileContainerName = fileContainerName; - this.resource = resource; - - if (existingTabs == null) - throw new NullPointerException("TabbedPane is null"); + public final JTabbedPane tabs; + public final JLabel label; + private DelayTabbedPaneThread probablyABadIdea; + private long startedDragging = 0; + public final String tabName; + public final String fileContainerName; + public final ResourceViewer resource; + private static long lastMouseClick = System.currentTimeMillis(); + public final static MouseListener buttonHoverAnimation = new ButtonHoverAnimation(); + public static final Color BLANK_COLOR = new Color(0, 0, 0, 0); - this.tabs = existingTabs; - setOpaque(false); + public TabbedPane(int tabIndex, String tabWorkingName, String fileContainerName, String name, final DraggableTabbedPane existingTabs, ResourceViewer resource) { + // unset default FlowLayout' gaps + super(new FlowLayout(FlowLayout.LEFT, 0, 0)); - // make JLabel read titles from JTabbedPane - label = new MaxWidthJLabel(tabName, 400, 20); + this.tabName = name; + this.fileContainerName = fileContainerName; + this.resource = resource; - this.add(label); - // add more space between the label and the button - label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5)); - // tab button - JButton exitButton = new CloseButton(); - this.add(exitButton); - // add more space to the top of the component - setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0)); - - //define the right click pop-up menu - JPopupMenu rightClickMenu = new JPopupMenu(); - JMenuItem closeAllTabs = new JMenuItem(TranslatedStrings.CLOSE_ALL_BUT_THIS + ": " + name); - JMenuItem closeTab = new JMenuItem(TranslatedStrings.CLOSE_TAB + ": " + name); - - rightClickMenu.add(closeAllTabs); - rightClickMenu.add(closeTab); - //setComponentPopupMenu(rightClickMenu); - - exitButton.setComponentPopupMenu(rightClickMenu); - exitButton.addMouseListener(new MouseClickedListener(e -> - { - if (this.getTabIndex() != -1) - existingTabs.remove(this.getTabIndex()); - })); - - closeTab.addActionListener(e -> - { - if (this.getTabIndex() != -1) - existingTabs.remove(this.getTabIndex()); - }); - closeAllTabs.addActionListener(e -> - { + if (existingTabs == null) + throw new NullPointerException("TabbedPane is null"); - while (true) - { - if (existingTabs.getTabCount() <= 1) - return; - - if (this.getTabIndex() != 0) - existingTabs.remove(0); - else - existingTabs.remove(1); - } - }); - - //tab dragging - if(BytecodeViewer.EXPERIMENTAL_TAB_CODE) - { + this.tabs = existingTabs; + setOpaque(false); + + // make JLabel read titles from JTabbedPane + label = new MaxWidthJLabel(tabName, 400, 20); + + this.add(label); + // add more space between the label and the button + label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5)); + // tab button + JButton exitButton = new CloseButton(); + // add more space to the top of the component + setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0)); + + //define the right click pop-up menu + JPopupMenu rightClickMenu = new JPopupMenu(); + this.putClientProperty("index", this.getTabIndex()); + JMenuItem closeAllTabs = new JMenuItem(TranslatedStrings.CLOSE_ALL_BUT_THIS + ": " + name); + JMenuItem closeTab = new JMenuItem(TranslatedStrings.CLOSE_TAB + ": " + name); + + rightClickMenu.add(closeAllTabs); + rightClickMenu.add(closeTab); + //setComponentPopupMenu(rightClickMenu); + + exitButton.setComponentPopupMenu(rightClickMenu); + exitButton.addMouseListener(new MouseClickedListener(e -> + { + if (this.getTabIndex() != -1) + existingTabs.remove(this.getTabIndex()); + })); + + closeTab.addActionListener(e -> + { + if (this.getTabIndex() != -1) + existingTabs.remove(this.getTabIndex()); + }); + closeAllTabs.addActionListener(e -> + { + + while (true) { + if (existingTabs.getTabCount() <= 1) + return; + + if (this.getTabIndex() != 0) + existingTabs.remove(0); + else + existingTabs.remove(1); + } + }); + + //tab dragging + if (BytecodeViewer.EXPERIMENTAL_TAB_CODE) { /*label.addMouseListener(new MouseListener() { @Override public void mouseClicked(MouseEvent e) {} @Override public void mouseEntered(MouseEvent arg0) { @@ -142,82 +132,112 @@ public class TabbedPane extends JPanel stopDragging(e.getX(), e.getY()); } });*/ - - this.addMouseListener(new MouseListener() { - @Override public void mouseClicked(MouseEvent e) {} - @Override public void mouseEntered(MouseEvent arg0) {} - @Override public void mouseExited(MouseEvent arg0) {} - @Override public void mousePressed(MouseEvent e) { - onMousePressed(e); - } - @Override public void mouseReleased(MouseEvent e) { - stopDragging(e.getX(), e.getY()); - } - }); - } - - //middle click close - if(BytecodeViewer.EXPERIMENTAL_TAB_CODE) - { - this.addMouseListener(new MouseAdapter() - { - @Override - public void mouseReleased(MouseEvent e) - { - if (e.getButton() != MouseEvent.BUTTON2) - return; - - final int i = existingTabs.indexOfTabComponent(TabbedPane.this); - if (i != -1) - existingTabs.remove(i); - } - }); - } - } - private void stopDragging(int mouseX, int mouseY) - { - if (System.currentTimeMillis() - startedDragging >= 210) - { - Rectangle bounds = new Rectangle(1, 1, mouseX, mouseY); - System.out.println("debug-5: " + mouseX + ", " + mouseY); - - int totalTabs = BytecodeViewer.viewer.workPane.tabs.getTabCount(); - int index = -1; - for (int i = 0; i < totalTabs; i++) - { - Component c = BytecodeViewer.viewer.workPane.tabs.getTabComponentAt(i); - - if (c != null && bounds.intersects(c.getBounds())) - index = i; //replace this tabs position - } + this.addMouseListener(new MouseListener() { + @Override + public void mouseClicked(MouseEvent e) { + } - if (index == -1) - { - for (int i = 0; i < totalTabs; i++) - { - Component c = BytecodeViewer.viewer.workPane.tabs.getTabComponentAt(i); - //do some check to see if it's past the X or Y - if (c != null) { - System.out.println("debug-6: " + c.getBounds()); - } - } - } + @Override + public void mouseEntered(MouseEvent arg0) { + } + + @Override + public void mouseExited(MouseEvent arg0) { + } + + @Override + public void mousePressed(MouseEvent e) { + onMousePressed(e); + } + + @Override + public void mouseReleased(MouseEvent e) { + } + }); + } + + //middle click close + if (BytecodeViewer.EXPERIMENTAL_TAB_CODE) { + this.addMouseListener(new MouseAdapter() { + @Override + public void mouseReleased(MouseEvent e) { + if (e.getButton() != MouseEvent.BUTTON2) + return; + + final int i = existingTabs.indexOfTabComponent(TabbedPane.this); + if (i != -1) + existingTabs.remove(i); + } + }); + } + } + + private void stopDragging(int mouseX, int mouseY) { + if (System.currentTimeMillis() - startedDragging >= 210) { + if (mouseX < 0) { + mouseX = 0; + } + Rectangle bounds = new Rectangle(1, 1, mouseX, mouseY); + System.out.println("debug-5: " + mouseX + ", " + mouseY); + + int totalTabs = BytecodeViewer.viewer.workPane.tabs.getTabCount(); + int curIndex = getTabIndex(); + int toIndex = -1; + + //Set up the indexes of our tabs. + for (int i = 0; i < totalTabs; i++) { + Component c = BytecodeViewer.viewer.workPane.tabs.getTabComponentAt(i); + System.err.println("Our bounds: " + bounds + " component: " + c.getBounds() + " intersects: " + bounds.intersects(c.getBounds())); + if (bounds.intersects(c.getBounds()) && c != this) { + toIndex = i; + } + } + + System.err.println(totalTabs + " " + curIndex + " " + toIndex); + + if (toIndex == totalTabs) { + System.err.println("here"); + } else if (curIndex > toIndex) { + if (toIndex == -1) { + toIndex = 0; + } + // [tab0=index0][tab1=index1] + // ---> == remove(tab0) + // [tab1=index0] + // add(tab0) + // [tab1=index0][tab0=index1] + + Component c = BytecodeViewer.viewer.workPane.tabs.getTabComponentAt(toIndex + 1); + System.err.println("here1"); +// BytecodeViewer.viewer.workPane.tabs.remove(curIndex - 1); // 0 +// BytecodeViewer.viewer.workPane.tabs.add(BytecodeViewer.viewer.workPane.op); +// BytecodeViewer.viewer.workPane.tabs.setTabComponentAt(curIndex, BytecodeViewer.viewer.workPane.tabs.getTabComponentAt(curIndex - 1)); + } else { + BytecodeViewer.viewer.workPane.tabs.remove(curIndex); // 0 + BytecodeViewer.viewer.workPane.tabs.add(resource); + BytecodeViewer.viewer.workPane.tabs.setTabComponentAt(toIndex, this); + } + + if (toIndex == -1) { + for (int i = 0; i < totalTabs; i++) { + Component c = BytecodeViewer.viewer.workPane.tabs.getTabComponentAt(i); + //do some check to see if it's past the X or Y + if (c != null) { + System.out.println("debug-6: " + c.getBounds()); + } + } + } + + } + + SwingUtilities.invokeLater(() -> + { + label.setBackground(BLANK_COLOR); + label.updateUI(); + }); + } - if (index != -1) - { - BytecodeViewer.viewer.workPane.tabs.remove(this); - BytecodeViewer.viewer.workPane.tabs.setTabComponentAt(index, this); - } - } - - SwingUtilities.invokeLater(() -> - { - label.setBackground(BLANK_COLOR); - label.updateUI(); - }); - } - public void onMousePressed(MouseEvent e) { BytecodeViewer.viewer.workPane.tabs.dispatchEvent(e); @@ -232,8 +252,7 @@ public class TabbedPane extends JPanel probablyABadIdea = new DelayTabbedPaneThread(TabbedPane.this); probablyABadIdea.start(); repaint(); - System.out.println(e.getX()+", "+e.getY()); - Rectangle bounds = new Rectangle(1, 1, e.getX(), e.getY()); + Rectangle bounds = new Rectangle(e.getX(), e.getY(), e.getX() + this.getX(), e.getY()); for(int i = 0; i < BytecodeViewer.viewer.workPane.tabs.getTabCount(); i++) { Component c = BytecodeViewer.viewer.workPane.tabs.getTabComponentAt(i); @@ -246,10 +265,10 @@ public class TabbedPane extends JPanel stopDragging(e.getX(), e.getY()); } } - - private static final long serialVersionUID = -4774885688297538774L; - public int getTabIndex() { - return tabs.indexOfTabComponent(this); - } + private static final long serialVersionUID = -4774885688297538774L; + + public int getTabIndex() { + return tabs.indexOfTabComponent(this); + } } diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/Workspace.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/Workspace.java index cf42fe6a..a2ff0647 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/Workspace.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/Workspace.java @@ -1,9 +1,6 @@ package the.bytecode.club.bytecodeviewer.gui.resourceviewer; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.FlowLayout; -import java.awt.Rectangle; +import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.HashSet; @@ -12,7 +9,8 @@ import javax.swing.JButton; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JPopupMenu; -import javax.swing.JTabbedPane; + +import com.github.weisj.darklaf.components.CloseButton; import the.bytecode.club.bytecodeviewer.BytecodeViewer; import the.bytecode.club.bytecodeviewer.decompilers.Decompiler; import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ClassViewer; @@ -45,7 +43,7 @@ import static the.bytecode.club.bytecodeviewer.Constants.BLOCK_TAB_MENU; ***************************************************************************/ /** - * The pane that contains all of the resources as tabs. + * This pane contains all the resources, as tabs. * * @author Konloch * @author WaterWolf @@ -54,7 +52,7 @@ import static the.bytecode.club.bytecodeviewer.Constants.BLOCK_TAB_MENU; public class Workspace extends TranslatedVisibleComponent { - public final JTabbedPane tabs; + public final DraggableTabbedPane tabs; public final JPanel buttonPanel; public final JButton refreshClass; public final Set openedTabs = new HashSet<>(); @@ -63,8 +61,8 @@ public class Workspace extends TranslatedVisibleComponent { super("Workspace", TranslatedComponents.WORK_SPACE); - this.tabs = new JTabbedPane(); - + this.tabs = new DraggableTabbedPane(); + JPopupMenu popUp = new JPopupMenu(); JMenuItem closeAllTabs = new JMenuItem("Close All But This"); JMenuItem closeTab = new JMenuItem("Close Tab"); @@ -72,28 +70,28 @@ public class Workspace extends TranslatedVisibleComponent { TabExitButton tabExitButton = (TabExitButton) ((JPopupMenu)((JMenuItem) e.getSource()).getParent()).getInvoker(); final int index = tabExitButton.getTabIndex(); - + if (index != -1) tabs.remove(index); }); - + closeAllTabs.addActionListener(e -> { TabExitButton tabExitButton = (TabExitButton) ((JPopupMenu)((JMenuItem) e.getSource()).getParent()).getInvoker(); final int index = tabExitButton.getTabIndex(); - + while (true) { if (tabs.getTabCount() <= 1) return; - + if (index != 0) tabs.remove(0); else tabs.remove(1); } }); - + tabs.addMouseListener(new MouseListener() { @Override @@ -108,11 +106,11 @@ public class Workspace extends TranslatedVisibleComponent { if (BLOCK_TAB_MENU) return; - + if (e.getButton() == 3) { Rectangle bounds = new Rectangle(1, 1, e.getX(), e.getY()); - + for (int i = 0; i < BytecodeViewer.viewer.workPane.tabs.getTabCount(); i++) { Component c = BytecodeViewer.viewer.workPane.tabs.getTabComponentAt(i); @@ -136,7 +134,7 @@ public class Workspace extends TranslatedVisibleComponent popUp.add(closeAllTabs); popUp.add(closeTab); - + if (!BLOCK_TAB_MENU) tabs.setComponentPopupMenu(popUp); @@ -155,7 +153,7 @@ public class Workspace extends TranslatedVisibleComponent buttonPanel.add(refreshClass); buttonPanel.setVisible(false); - + getContentPane().add(buttonPanel, BorderLayout.SOUTH); tabs.addContainerListener(new TabRemovalEvent()); @@ -175,7 +173,7 @@ public class Workspace extends TranslatedVisibleComponent { addResource(container, name, new FileViewer(container, name)); } - + private void addResource(final ResourceContainer container, final String name, final ResourceViewer resourceView) { // Warn user and prevent 'nothing' from opening if no Decompiler is selected @@ -186,12 +184,12 @@ public class Workspace extends TranslatedVisibleComponent BytecodeViewer.showMessage(TranslatedStrings.SUGGESTED_FIX_NO_DECOMPILER_WARNING.toString()); return; } - + //unlock the refresh button BytecodeViewer.viewer.workPane.refreshClass.setEnabled(true); - + final String workingName = container.getWorkingName(name); - + //create a new tab if the resource isn't opened currently if (!openedTabs.contains(workingName)) { @@ -200,7 +198,7 @@ public class Workspace extends TranslatedVisibleComponent else //if the resource is already opened select this tab as the active one { //TODO openedTabs could be changed to a HashMap for faster lookups - + //search through each tab for(int i = 0; i < tabs.getTabCount(); i++) { @@ -214,33 +212,33 @@ public class Workspace extends TranslatedVisibleComponent } } } - + public void addResourceToTab(ResourceViewer resourceView, String workingName, String containerName, String name) { //start processing the resource to be viewed if(resourceView instanceof ClassViewer) resourceView.refresh(null); - + //add the resource view to the tabs tabs.add(resourceView); - + //get the resource view index final int tabIndex = tabs.indexOfComponent(resourceView); - + //create a new tabbed pane - TabbedPane tabbedPane = new TabbedPane(tabIndex, workingName, containerName, name, tabs, resourceView); - resourceView.tabbedPane = tabbedPane; + resourceView.tabbedPane = new TabbedPane(tabIndex, workingName, containerName, name, tabs, resourceView); resourceView.resource.workingName = workingName; - + //set the tabs index - tabs.setTabComponentAt(tabIndex, tabbedPane); - +// tabs.setTabComponentAt(tabIndex, tabbedPane); + tabs.setTabComponentAt(tabIndex, new CloseButtonComponent(tabs)); + //open the tab that was just added tabs.setSelectedIndex(tabIndex); - + //set resource as opened in a tab openedTabs.add(workingName); - + //refresh the tab title resourceView.refreshTitle(); } @@ -258,6 +256,6 @@ public class Workspace extends TranslatedVisibleComponent tabs.removeAll(); tabs.updateUI(); } - + private static final long serialVersionUID = 6542337997679487946L; } From ae6911658ca14099d3e3445354088b349ce7caf7 Mon Sep 17 00:00:00 2001 From: Cody Date: Mon, 23 Jan 2023 23:13:36 -0800 Subject: [PATCH 2/2] Enabled tabs to be rearranged. Did not add functionality for a tab to be dropped out. We could possibly add it at a later time, also add a setting to toggle it on/off? Recommend to gather feedback to see if that is something wanted. --- .../club/bytecodeviewer/BytecodeViewer.java | 2 - .../resourceviewer/CloseButtonComponent.java | 43 +++++ .../resourceviewer/DraggableTabbedPane.java | 5 - .../gui/resourceviewer/TabbedPane.java | 166 +----------------- .../gui/resourceviewer/Workspace.java | 1 - 5 files changed, 45 insertions(+), 172 deletions(-) diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/BytecodeViewer.java b/src/main/java/the/bytecode/club/bytecodeviewer/BytecodeViewer.java index 7126ea9a..a1e36460 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/BytecodeViewer.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/BytecodeViewer.java @@ -129,8 +129,6 @@ import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory; public class BytecodeViewer { - //TODO fix this for tab dragging & better tab controls - public static boolean EXPERIMENTAL_TAB_CODE = true; //the launch args called on BCV public static String[] launchArgs; diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/CloseButtonComponent.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/CloseButtonComponent.java index 277834b8..50c983d2 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/CloseButtonComponent.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/CloseButtonComponent.java @@ -2,14 +2,23 @@ package the.bytecode.club.bytecodeviewer.gui.resourceviewer; import com.android.tools.r8.internal.Cl; import com.github.weisj.darklaf.components.CloseButton; +import com.github.weisj.darklaf.listener.MouseClickListener; +import the.bytecode.club.bytecodeviewer.gui.components.listeners.MouseClickedListener; +import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings; import javax.swing.*; import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; public class CloseButtonComponent extends JPanel { private final JTabbedPane pane; + String title = ""; + public CloseButtonComponent(final JTabbedPane pane) { super(new FlowLayout(FlowLayout.LEFT, 0, 0)); if (pane == null) { @@ -33,6 +42,40 @@ public class CloseButtonComponent extends JPanel { label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5)); JButton button = new CloseButton(); add(button); + + JPopupMenu rightClickMenu = new JPopupMenu(); + JMenuItem closeAllTabs = new JMenuItem(String.valueOf(TranslatedStrings.CLOSE_ALL_BUT_THIS)); + JMenuItem closeTab = new JMenuItem(String.valueOf(TranslatedStrings.CLOSE_TAB)); + + rightClickMenu.add(closeAllTabs); + rightClickMenu.add(closeTab); + button.setComponentPopupMenu(rightClickMenu); + + button.addMouseListener(new MouseClickedListener(e -> + { + if (pane.indexOfTabComponent(CloseButtonComponent.this) != -1) + pane.remove(pane.indexOfTabComponent(CloseButtonComponent.this)); + })); + + closeTab.addActionListener(e -> + { + if (pane.indexOfTabComponent(CloseButtonComponent.this) != -1) + pane.remove(pane.indexOfTabComponent(CloseButtonComponent.this)); + }); + closeAllTabs.addActionListener(e -> + { + + while (true) { + if (pane.getTabCount() <= 1) + return; + + if (pane.indexOfTabComponent(CloseButtonComponent.this) != 0) + pane.remove(0); + else + pane.remove(1); + } + }); + setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0)); } diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/DraggableTabbedPane.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/DraggableTabbedPane.java index 3afcbfd8..14048d52 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/DraggableTabbedPane.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/DraggableTabbedPane.java @@ -1,6 +1,5 @@ package the.bytecode.club.bytecodeviewer.gui.resourceviewer; -import com.github.weisj.darklaf.components.CloseButton; import the.bytecode.club.bytecodeviewer.BytecodeViewer; import javax.swing.*; @@ -8,10 +7,6 @@ import java.awt.*; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.dnd.*; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionAdapter; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/TabbedPane.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/TabbedPane.java index 4f491e09..6e69083a 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/TabbedPane.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/TabbedPane.java @@ -76,166 +76,8 @@ public class TabbedPane extends JPanel { this.add(label); // add more space between the label and the button label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5)); - // tab button - JButton exitButton = new CloseButton(); // add more space to the top of the component setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0)); - - //define the right click pop-up menu - JPopupMenu rightClickMenu = new JPopupMenu(); - this.putClientProperty("index", this.getTabIndex()); - JMenuItem closeAllTabs = new JMenuItem(TranslatedStrings.CLOSE_ALL_BUT_THIS + ": " + name); - JMenuItem closeTab = new JMenuItem(TranslatedStrings.CLOSE_TAB + ": " + name); - - rightClickMenu.add(closeAllTabs); - rightClickMenu.add(closeTab); - //setComponentPopupMenu(rightClickMenu); - - exitButton.setComponentPopupMenu(rightClickMenu); - exitButton.addMouseListener(new MouseClickedListener(e -> - { - if (this.getTabIndex() != -1) - existingTabs.remove(this.getTabIndex()); - })); - - closeTab.addActionListener(e -> - { - if (this.getTabIndex() != -1) - existingTabs.remove(this.getTabIndex()); - }); - closeAllTabs.addActionListener(e -> - { - - while (true) { - if (existingTabs.getTabCount() <= 1) - return; - - if (this.getTabIndex() != 0) - existingTabs.remove(0); - else - existingTabs.remove(1); - } - }); - - //tab dragging - if (BytecodeViewer.EXPERIMENTAL_TAB_CODE) { - /*label.addMouseListener(new MouseListener() { - @Override public void mouseClicked(MouseEvent e) {} - @Override public void mouseEntered(MouseEvent arg0) { - } - @Override public void mouseExited(MouseEvent arg0) { - } - @Override public void mousePressed(MouseEvent e) { - onMousePressed(e); - } - @Override public void mouseReleased(MouseEvent e) { - stopDragging(e.getX(), e.getY()); - } - });*/ - - this.addMouseListener(new MouseListener() { - @Override - public void mouseClicked(MouseEvent e) { - } - - @Override - public void mouseEntered(MouseEvent arg0) { - } - - @Override - public void mouseExited(MouseEvent arg0) { - } - - @Override - public void mousePressed(MouseEvent e) { - onMousePressed(e); - } - - @Override - public void mouseReleased(MouseEvent e) { - } - }); - } - - //middle click close - if (BytecodeViewer.EXPERIMENTAL_TAB_CODE) { - this.addMouseListener(new MouseAdapter() { - @Override - public void mouseReleased(MouseEvent e) { - if (e.getButton() != MouseEvent.BUTTON2) - return; - - final int i = existingTabs.indexOfTabComponent(TabbedPane.this); - if (i != -1) - existingTabs.remove(i); - } - }); - } - } - - private void stopDragging(int mouseX, int mouseY) { - if (System.currentTimeMillis() - startedDragging >= 210) { - if (mouseX < 0) { - mouseX = 0; - } - Rectangle bounds = new Rectangle(1, 1, mouseX, mouseY); - System.out.println("debug-5: " + mouseX + ", " + mouseY); - - int totalTabs = BytecodeViewer.viewer.workPane.tabs.getTabCount(); - int curIndex = getTabIndex(); - int toIndex = -1; - - //Set up the indexes of our tabs. - for (int i = 0; i < totalTabs; i++) { - Component c = BytecodeViewer.viewer.workPane.tabs.getTabComponentAt(i); - System.err.println("Our bounds: " + bounds + " component: " + c.getBounds() + " intersects: " + bounds.intersects(c.getBounds())); - if (bounds.intersects(c.getBounds()) && c != this) { - toIndex = i; - } - } - - System.err.println(totalTabs + " " + curIndex + " " + toIndex); - - if (toIndex == totalTabs) { - System.err.println("here"); - } else if (curIndex > toIndex) { - if (toIndex == -1) { - toIndex = 0; - } - // [tab0=index0][tab1=index1] - // ---> == remove(tab0) - // [tab1=index0] - // add(tab0) - // [tab1=index0][tab0=index1] - - Component c = BytecodeViewer.viewer.workPane.tabs.getTabComponentAt(toIndex + 1); - System.err.println("here1"); -// BytecodeViewer.viewer.workPane.tabs.remove(curIndex - 1); // 0 -// BytecodeViewer.viewer.workPane.tabs.add(BytecodeViewer.viewer.workPane.op); -// BytecodeViewer.viewer.workPane.tabs.setTabComponentAt(curIndex, BytecodeViewer.viewer.workPane.tabs.getTabComponentAt(curIndex - 1)); - } else { - BytecodeViewer.viewer.workPane.tabs.remove(curIndex); // 0 - BytecodeViewer.viewer.workPane.tabs.add(resource); - BytecodeViewer.viewer.workPane.tabs.setTabComponentAt(toIndex, this); - } - - if (toIndex == -1) { - for (int i = 0; i < totalTabs; i++) { - Component c = BytecodeViewer.viewer.workPane.tabs.getTabComponentAt(i); - //do some check to see if it's past the X or Y - if (c != null) { - System.out.println("debug-6: " + c.getBounds()); - } - } - } - - } - - SwingUtilities.invokeLater(() -> - { - label.setBackground(BLANK_COLOR); - label.updateUI(); - }); } public void onMousePressed(MouseEvent e) @@ -260,15 +102,11 @@ public class TabbedPane extends JPanel { BytecodeViewer.viewer.workPane.tabs.setSelectedIndex(i); } } - else - { - stopDragging(e.getX(), e.getY()); - } } private static final long serialVersionUID = -4774885688297538774L; - public int getTabIndex() { + /*public int getTabIndex() { return tabs.indexOfTabComponent(this); - } + }*/ } diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/Workspace.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/Workspace.java index a2ff0647..59df7675 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/Workspace.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/Workspace.java @@ -230,7 +230,6 @@ public class Workspace extends TranslatedVisibleComponent resourceView.resource.workingName = workingName; //set the tabs index -// tabs.setTabComponentAt(tabIndex, tabbedPane); tabs.setTabComponentAt(tabIndex, new CloseButtonComponent(tabs)); //open the tab that was just added