/* * Copyright ©1998-2020 by Richard A. Wilkes. All rights reserved. * * This Source Code Form is subject to the terms of the Mozilla Public * License, version 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This Source Code Form is "Incompatible With Secondary Licenses", as * defined by the Mozilla Public License, version 2.0. */ package com.trollworks.gcs.ui.widget.dock; import com.trollworks.gcs.ui.Colors; import com.trollworks.gcs.ui.MouseCapture; import com.trollworks.gcs.ui.TextDrawing; import com.trollworks.gcs.ui.UIUtilities; import com.trollworks.gcs.utility.I18n; import com.trollworks.gcs.utility.text.Numbers; import com.trollworks.gcs.utility.text.Text; import java.awt.Color; import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Insets; import java.awt.MouseInfo; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.swing.JComponent; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.SwingConstants; import javax.swing.UIManager; public class ShowTabsButton extends JComponent implements MouseListener, MouseMotionListener, ComponentListener, ActionListener { private static final int MARGIN = 2; private boolean mInMouseDown; private boolean mPressed; private boolean mShowBorder; private Set<DockTab> mHidden = new HashSet<>(); public ShowTabsButton() { setOpaque(false); setBackground(null); setFont(UIManager.getFont("Label.font")); setToolTipText(Text.wrapPlainTextForToolTip(I18n.Text("Show Hidden Tabs List"))); setCursor(Cursor.getDefaultCursor()); addMouseListener(this); addMouseMotionListener(this); addComponentListener(this); } public void addHidden(DockTab tab) { mHidden.add(tab); repaint(); } public void clearHidden() { mHidden.clear(); repaint(); } public boolean hasHidden() { return !mHidden.isEmpty(); } public boolean isHidden(Component component) { if (component instanceof DockTab) { return mHidden.contains(component); } if (component == this) { return !hasHidden(); } return false; } @Override public Dimension getPreferredSize() { Insets insets = getInsets(); return new Dimension(getPreferredWidth(), MARGIN + insets.top + TextDrawing.getFontHeight(getFont()) + insets.bottom + MARGIN); } @Override public Dimension getMinimumSize() { return getPreferredSize(); } public int getPreferredWidth() { Insets insets = getInsets(); return MARGIN + insets.left + TextDrawing.getSimpleWidth(getFont(), getText()) + insets.right + MARGIN; } private String getText() { return "»" + Numbers.format(mHidden.size()); } @Override protected void paintComponent(Graphics gc) { Insets insets = getInsets(); int x = insets.left; int y = insets.top; int width = getWidth() - (insets.left + insets.right); int height = getHeight() - (insets.top + insets.bottom); if (mInMouseDown && mPressed) { gc.setColor(Colors.adjustBrightness(getBackground(), -0.2f)); gc.fillRect(x, y, width, height); } if (mShowBorder || mInMouseDown) { gc.setColor(Colors.adjustBrightness(getBackground(), -0.4f)); gc.drawRect(x, y, width - 1, height - 1); } gc.setFont(getFont()); gc.setColor(Color.BLACK); String text = getText(); Rectangle bounds = getBounds(); bounds.x = insets.left; bounds.y = insets.top; bounds.width -= insets.left + insets.right; bounds.height -= insets.top + insets.bottom; TextDrawing.draw(gc, bounds, text, SwingConstants.CENTER, SwingConstants.CENTER); } public void click() { JPopupMenu menu = new JPopupMenu(); List<DockTab> tabs = new ArrayList<>(mHidden); Collections.sort(tabs); for (DockTab tab : tabs) { JMenuItem item = new JMenuItem(tab.getFullTitle(), tab.getIcon()); item.putClientProperty(this, tab.getDockable()); item.addActionListener(this); menu.add(item); } menu.show(this, 0, 0); } @Override public void actionPerformed(ActionEvent event) { Dockable dockable = (Dockable) ((JMenuItem) event.getSource()).getClientProperty(this); dockable.getDockContainer().setCurrentDockable(dockable); } private boolean isOver(int x, int y) { return x >= 0 && y >= 0 && x < getWidth() && y < getHeight(); } @Override public void mouseEntered(MouseEvent event) { mShowBorder = true; repaint(); } @Override public void mouseMoved(MouseEvent event) { // Unused } @Override public void mousePressed(MouseEvent event) { if (!event.isPopupTrigger() && event.getButton() == 1) { mInMouseDown = true; mPressed = true; repaint(); MouseCapture.start(this, Cursor.getDefaultCursor()); } } @Override public void mouseDragged(MouseEvent event) { boolean wasPressed = mPressed; mPressed = isOver(event.getX(), event.getY()); if (mPressed != wasPressed) { repaint(); } } @Override public void mouseReleased(MouseEvent event) { mouseDragged(event); mShowBorder = mPressed; mInMouseDown = false; MouseCapture.stop(this); if (mPressed) { mPressed = false; click(); } repaint(); } @Override public void mouseClicked(MouseEvent event) { // Unused } @Override public void mouseExited(MouseEvent event) { mShowBorder = false; repaint(); } private void updateRollOver() { boolean wasBorderShown = mShowBorder; Point location = MouseInfo.getPointerInfo().getLocation(); UIUtilities.convertPointFromScreen(location, this); mShowBorder = isOver(location.x, location.y); if (wasBorderShown != mShowBorder) { repaint(); } } @Override public void componentResized(ComponentEvent event) { updateRollOver(); } @Override public void componentMoved(ComponentEvent event) { updateRollOver(); } @Override public void componentShown(ComponentEvent event) { updateRollOver(); } @Override public void componentHidden(ComponentEvent event) { updateRollOver(); } }