diff --git a/.gitignore b/.gitignore index 5cd45f5..fe7ee24 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,9 @@ release.properties dependency-reduced-pom.xml buildNumber.properties .mvn/timing.properties +.settings/ +.project +.classpath # ========================= # Operating System Files diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..66b8e66 --- /dev/null +++ b/pom.xml @@ -0,0 +1,39 @@ + + 4.0.0 + com.github.oxygen-plugins + common-gui + 0.0.1-SNAPSHOT + Common GUI utils + This project contains frequently used GUI utils, so they can be used in several projects. + + + com.github.oxygen-plugins + common-xml + v0.0.1 + + + joda-time + joda-time + 2.3 + + + + + jitpack.io + https://jitpack.io + + + + + + maven-compiler-plugin + 3.5.1 + + 1.7 + 1.7 + + + + + \ No newline at end of file diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/borders/ResaizeableLayout.java b/src/main/java/com/github/oxygenPlugins/common/gui/borders/ResaizeableLayout.java new file mode 100644 index 0000000..345d58b --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/borders/ResaizeableLayout.java @@ -0,0 +1,70 @@ +package com.github.oxygenPlugins.common.gui.borders; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.LayoutManager2; + +public class ResaizeableLayout implements LayoutManager2 { + + @Override + public void addLayoutComponent(String arg0, Component arg1) { + // TODO Auto-generated method stub + + } + + @Override + public void layoutContainer(Container arg0) { + // TODO Auto-generated method stub + + } + + @Override + public Dimension minimumLayoutSize(Container arg0) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Dimension preferredLayoutSize(Container arg0) { + // TODO Auto-generated method stub + return null; + } + + @Override + public void removeLayoutComponent(Component arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void addLayoutComponent(Component comp, Object constraints) { + // TODO Auto-generated method stub + + } + + @Override + public float getLayoutAlignmentX(Container target) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public float getLayoutAlignmentY(Container target) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public void invalidateLayout(Container target) { + // TODO Auto-generated method stub + + } + + @Override + public Dimension maximumLayoutSize(Container target) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/borders/ResizeableAbsolutePane.java b/src/main/java/com/github/oxygenPlugins/common/gui/borders/ResizeableAbsolutePane.java new file mode 100644 index 0000000..1d6a95f --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/borders/ResizeableAbsolutePane.java @@ -0,0 +1,157 @@ +package com.github.oxygenPlugins.common.gui.borders; + +import java.awt.Dimension; +import java.awt.GridBagLayout; +import java.awt.Rectangle; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.util.ArrayList; +import java.util.HashMap; + +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.SwingConstants; + +public class ResizeableAbsolutePane { + private final JPanel panel = new JPanel(); + HashMap> compByXStart = new HashMap>(); + HashMap> compByXEnd = new HashMap>(); + HashMap> compByYStart = new HashMap>(); + HashMap> compByYEnd = new HashMap>(); + private Dimension panelSize; + private final ArrayList allRmls = new ArrayList(); + private final int[] cols; + private final int[] rows; + + public ResizeableAbsolutePane(int cols, int rows){ + this.cols = new int[cols]; + this.rows = new int[rows]; + panel.setLayout(null); + this.panelSize = panel.getSize(); + int colWidth = this.panelSize.width / cols; + int rowHeight = this.panelSize.height / rows; + for (int i = 0; i < this.cols.length; i++) { + this.cols[i] = colWidth; + } + for (int i = 0; i < this.rows.length; i++) { + this.rows[i] = rowHeight; + } + this.panel.addComponentListener(new ComponentListener() { + + @Override + public void componentShown(ComponentEvent arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void componentResized(ComponentEvent arg0) { +// Dimension size = panelSize; + panelSize = panel.getSize(); +// for (ResizeableMouseListener rml : allRmls) { +//// rml.resize(size, panelSize); +// } + } + + @Override + public void componentMoved(ComponentEvent arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void componentHidden(ComponentEvent arg0) { + // TODO Auto-generated method stub + + } + }); + } + + + public void add(JComponent comp, int x, int y, int width, int height) { + makeResizeable(comp, x, y, width, height); + + panel.add(comp); + comp.setBounds(getBounds(x, y, width, height)); + panel.repaint(); + + } + + private Rectangle getBounds( int x, int y, int width, int height){ + int rx = 0; + int ry = 0; + int rwidth = 0; + int rheight = 0; + for (int i = 0; i < this.cols.length; i++) { + if(i < x){ + rx += this.cols[i]; + } else { + rwidth = this.cols[i]; + } + } + for (int i = 0; i < this.rows.length; i++) { + if(i < x){ + ry += this.rows[i]; + } else { + rheight = this.rows[i]; + } + } + Rectangle rect = new Rectangle(rx, ry, rwidth, rheight); + return rect; + } + private void makeResizeable(JComponent comp, int x, int y, int width, + int height) { + HashMap> oppositeNeighbours = new HashMap>(); + oppositeNeighbours.put(SwingConstants.NORTH, ResizeableMouseListener.copy(this.compByYEnd.get(y))); + oppositeNeighbours.put(SwingConstants.SOUTH, ResizeableMouseListener.copy(this.compByYStart.get(y + height))); + oppositeNeighbours.put(SwingConstants.WEST, ResizeableMouseListener.copy(this.compByXEnd.get(x))); + oppositeNeighbours.put(SwingConstants.EAST, ResizeableMouseListener.copy(this.compByXStart.get(x + width))); + HashMap> inlineNeighbours = new HashMap>(); + inlineNeighbours.put(SwingConstants.NORTH, ResizeableMouseListener.copy(this.compByYStart.get(y))); + inlineNeighbours.put(SwingConstants.SOUTH, ResizeableMouseListener.copy(this.compByYEnd.get(y + height))); + inlineNeighbours.put(SwingConstants.WEST, ResizeableMouseListener.copy(this.compByXStart.get(x))); + inlineNeighbours.put(SwingConstants.EAST, ResizeableMouseListener.copy(this.compByXEnd.get(x + width))); + + + ResizeableMouseListener rml = new ResizeableMouseListener(comp, 6, inlineNeighbours, oppositeNeighbours, new GridBagLayout()); + this.allRmls.add(rml); + addCompToMap(rml, x, y, width, height); + } + + + + public JPanel asJPanel(){ + return this.panel; + } + + private void addCompToMap(ResizeableMouseListener rml, int x, int y, int width, int height){ + addCompToMap(compByXStart, rml, x); + addCompToMap(compByYStart, rml, y); + addCompToMap(compByXEnd, rml, x + width); + addCompToMap(compByYEnd, rml, y + height); + + } + + private void addCompToMap(HashMap> map, ResizeableMouseListener comp, int pos){ + if(!map.containsKey(pos)){ + map.put(pos, new ArrayList()); + } + map.get(pos).add(comp); + } + +// private class RMLPosition { +// ResizeableMouseListener rml; +// int x; +// int y; +// int w; +// int h; +// public RMLPosition(ResizeableMouseListener rml, int x, int y, int w, int h){ +// this.rml = rml; +// this.x = x; +// this.y = y; +// this.w = w; +// this.h = h; +// +// } +// } +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/borders/ResizeableMouseListener.java b/src/main/java/com/github/oxygenPlugins/common/gui/borders/ResizeableMouseListener.java new file mode 100644 index 0000000..21b651f --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/borders/ResizeableMouseListener.java @@ -0,0 +1,374 @@ +package com.github.oxygenPlugins.common.gui.borders; + +import java.awt.Component; +import java.awt.Cursor; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Point; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Set; + +import javax.swing.JComponent; +import javax.swing.SwingConstants; +import javax.swing.event.MouseInputAdapter; + +public class ResizeableMouseListener extends MouseInputAdapter { + + private final HashMap> oppositeNeighbours; + private final HashMap> insideNeighbours; + private final JComponent parent; + private final int borderWidth; + private final GridBagLayout grandParentGbl; + private final boolean resizeableOnEmptyBorder; + + public ResizeableMouseListener( + JComponent parent, + int borderWidth, + HashMap> insideNeighbours, + HashMap> oppositeNeighbours, + GridBagLayout grandParentGbl){ + this(parent,borderWidth, insideNeighbours, oppositeNeighbours, grandParentGbl, false); + } + + public ResizeableMouseListener( + JComponent parent, + int borderWidth, + HashMap> insideNeighbours, + HashMap> oppositeNeighbours, + GridBagLayout grandParentGbl, boolean resizeableOnEmptyBorder) { + this.parent = parent; + this.parent.addComponentListener(new ComponentListener() { + + @Override + public void componentShown(ComponentEvent arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void componentResized(ComponentEvent arg0) { + // TODO Auto-generated method stub + Component c = arg0.getComponent(); + if(c instanceof JComponent){ + JComponent jc = (JComponent) c; + jc.updateUI(); + } + } + + @Override + public void componentMoved(ComponentEvent arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void componentHidden(ComponentEvent arg0) { + // TODO Auto-generated method stub + + } + }); + this.borderWidth = borderWidth; + this.insideNeighbours = insideNeighbours; + this.oppositeNeighbours = oppositeNeighbours; + this.grandParentGbl = grandParentGbl; + this.resizeableOnEmptyBorder = resizeableOnEmptyBorder; + addNeighbours(this.oppositeNeighbours, false); + addNeighbours(this.insideNeighbours, true); + + parent.addMouseListener(this); + parent.addMouseMotionListener(this); + parent.addMouseWheelListener(this); + } + + public static ArrayList copy( + ArrayList org) { + if (org == null) + return null; + ArrayList copy = new ArrayList(); + copy.addAll(org); + return copy; + } + + private void addNeighbours( + HashMap> neighbourMap, + boolean inside) { + Set typeSet = neighbourMap.keySet(); + for (Integer type : typeSet) { + ArrayList neighbours = neighbourMap + .get(type); + if (neighbours != null) { + // for (Iterator i = + // neighbours.iterator(); i.hasNext();) { + // ResizeableMouseListener neigh = (ResizeableMouseListener) + // i.next(); + // neigh.addNeighbour(type, this); + // } + for (ResizeableMouseListener neigh : neighbours) { + if (neigh != this) { + if (inside) { + neigh.addInsideNeighbour(type, this); + } else { + neigh.addOppositeNeighbour(reverseDragType(type), + this); + } + } + } + } + } + } + + private int[] cursorsByDragType = { -1, Cursor.N_RESIZE_CURSOR, -1, + Cursor.E_RESIZE_CURSOR, -1, Cursor.S_RESIZE_CURSOR, -1, + Cursor.W_RESIZE_CURSOR }; + + @Override + public void mouseMoved(MouseEvent e) { + dragType = getDragType(e.getPoint()); + Component comp = e.getComponent(); + if (dragType < 0 && !isDragging) { + comp.setCursor(Cursor.getDefaultCursor()); + } else { + comp.setCursor(Cursor + .getPredefinedCursor(cursorsByDragType[dragType])); + } + } + + @Override + public void mouseEntered(MouseEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void mouseExited(MouseEvent e) { + if (!isDragging) { + Component comp = e.getComponent(); + comp.setCursor(Cursor.getDefaultCursor()); + } + } + + private Point startPos = null; + private int dragType; + private boolean isDragging = false; + + @Override + public void mousePressed(MouseEvent e) { + Point p = e.getPoint(); + dragType = getDragType(p); + if (dragType != -1) { + startPos = e.getPoint(); + this.isDragging = true; + } else { + startPos = null; + } + + } + + @Override + public void mouseDragged(MouseEvent me) { + Point startPos = this.startPos; + if (startPos != null) { + resize(this.parent, startPos, me, dragType); + ArrayList oppNeighs = oppositeNeighbours + .get(dragType); + ArrayList innNeighs = insideNeighbours + .get(dragType); + if (oppNeighs != null) { + for (ResizeableMouseListener neigh : oppNeighs) { + resize(neigh.getParent(), startPos, me, + reverseDragType(dragType)); + neigh.didResized(); + } + } + if (innNeighs != null) { + for (ResizeableMouseListener neigh : innNeighs) { + resize(neigh.getParent(), startPos, me, dragType); + neigh.didResized(); + } + } + } + } + + @Override + public void mouseReleased(MouseEvent e) { + // TODO Auto-generated method stub + didResized(); +// for (ArrayList neighlist : oppositeNeighbours +// .values()) { +// if (neighlist != null) { +// for (ResizeableMouseListener neigh : neighlist) { +// neigh.didResized(); +// } +// } +// } +// for (ArrayList neighlist : insideNeighbours +// .values()) { +// if (neighlist != null) { +// for (ResizeableMouseListener neigh : neighlist) { +// neigh.didResized(); +// } +// } +// } + this.isDragging = false; + Component comp = e.getComponent(); + comp.setCursor(Cursor.getDefaultCursor()); + } + + private int getDragType(Point p) { + int width = parent.getWidth(); + int height = parent.getHeight(); + + boolean onLeft = p.x <= this.borderWidth; + boolean onTop = p.y <= this.borderWidth; + boolean onRight = p.x >= width - this.borderWidth; + boolean onBottom = p.y >= height - this.borderWidth; + int dragType; + if (onTop) { + dragType = SwingConstants.NORTH; + } else if (onBottom) { + dragType = SwingConstants.SOUTH; + } else if (onLeft) { + dragType = SwingConstants.WEST; + } else if (onRight) { + dragType = SwingConstants.EAST; + } else { + dragType = -1; + } + ArrayList oppNeigh = this.oppositeNeighbours.get(dragType); + boolean hasNeigh = false; + if(oppNeigh != null){ + if(oppNeigh.size() > 0) + hasNeigh = true; + } + if(hasNeigh || this.resizeableOnEmptyBorder){ + return dragType; + } else { + return -1; + } + } + + private void resize(JComponent comp, Point startPos, MouseEvent me, + int dragType) { + int dx = me.getX() - startPos.x; + int dy = me.getY() - startPos.y; + switch (dragType) { + + case SwingConstants.NORTH: + comp.setBounds(comp.getX(), comp.getY() + dy, comp.getWidth(), + comp.getHeight() - dy); + break; + + case SwingConstants.SOUTH: + comp.setBounds(comp.getX(), comp.getY(), comp.getWidth(), + comp.getHeight() + dy); + if (comp == this.getParent()) + this.startPos = me.getPoint(); + break; + + case SwingConstants.WEST: + comp.setBounds(comp.getX() + dx, comp.getY(), comp.getWidth() - dx, + comp.getHeight()); + break; + + case SwingConstants.EAST: + comp.setBounds(comp.getX(), comp.getY(), comp.getWidth() + dx, + comp.getHeight()); + if (comp == this.getParent()) + this.startPos = me.getPoint(); + break; + + default: + break; + } + } + + public void didResized() { + GridBagConstraints gbc = this.grandParentGbl.getConstraints(this.parent); + + int columnWidth = this.parent.getWidth() / gbc.gridwidth; + int columnHeight = this.parent.getHeight() / gbc.gridheight; + if(gbc.gridwidth == 1){ + this.grandParentGbl.columnWidths[gbc.gridx] = columnWidth; + } + if(gbc.gridheight == 1){ + this.grandParentGbl.rowHeights[gbc.gridy] = columnHeight; + } +// for (int i = gbc.gridx; i < gbc.gridwidth + gbc.gridx; i++) { +// } +// +// for (int i = gbc.gridy; i < gbc.gridheight + gbc.gridy; i++) { +// } + +// double newWidth = this.parent.getWidth(); +// double newHeight = this.parent.getHeight(); +// double gparentWidth = this.parent.getParent().getWidth(); +// double gparentHeight = this.parent.getParent().getHeight(); +// +// +// gbc.weightx = newWidth / gparentWidth; +// gbc.weighty = newHeight / gparentHeight; +// this.grandParentGbl.setConstraints(this.parent, gbc); + + + + + this.parent.repaint(); + + } + + private int reverseDragType(int type) { + switch (type) { + case SwingConstants.NORTH: + return SwingConstants.SOUTH; + case SwingConstants.SOUTH: + return SwingConstants.NORTH; + case SwingConstants.WEST: + return SwingConstants.EAST; + case SwingConstants.EAST: + return SwingConstants.WEST; + + default: + return -1; + } + } + + public void addOppositeNeighbour(int type, ResizeableMouseListener neigh) { + if (oppositeNeighbours.get(type) == null) { + oppositeNeighbours.put(type, + new ArrayList()); + } + oppositeNeighbours.get(type).add(neigh); + } + + public void addInsideNeighbour(int type, ResizeableMouseListener neigh) { + if (insideNeighbours.get(type) == null) { + insideNeighbours + .put(type, new ArrayList()); + } + insideNeighbours.get(type).add(neigh); + } + + public JComponent getParent() { + return this.parent; + } + + // public void resize(Dimension oldSize, Dimension newSize) { + // if(oldSize.width > 0 && oldSize.height > 0){ + // resize(newSize.width / oldSize.width, newSize.height / oldSize.height); + // } + // } + // + // private void resize(double factX, double factY) { + // int x = (int) (actualDimension.getX() * factX); + // int y = (int) (actualDimension.getY() * factY); + // int w = (int) (actualDimension.getWidth() * factX); + // int h = (int) (actualDimension.getHeight() * factY); + // this.parent.setBounds(x, y, w, h); + // didResized(); + // } + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/borders/ResizeablePane.java b/src/main/java/com/github/oxygenPlugins/common/gui/borders/ResizeablePane.java new file mode 100644 index 0000000..9b52783 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/borders/ResizeablePane.java @@ -0,0 +1,125 @@ +package com.github.oxygenPlugins.common.gui.borders; + +import java.awt.Dimension; +import java.awt.GridBagLayout; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.util.ArrayList; +import java.util.HashMap; + +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.SwingConstants; + +import com.github.oxygenPlugins.common.gui.swing.SwingUtil; + + + +public class ResizeablePane { + private GridBagLayout gbl = new GridBagLayout(); + private final JPanel panel = new JPanel(); + HashMap> compByXStart = new HashMap>(); + HashMap> compByXEnd = new HashMap>(); + HashMap> compByYStart = new HashMap>(); + HashMap> compByYEnd = new HashMap>(); + @SuppressWarnings("unused") + private Dimension panelSize; + private final ArrayList allRmls = new ArrayList(); + + public ResizeablePane(int cols, int rows){ + panel.setLayout(gbl); + gbl.columnWidths = new int[cols]; + gbl.rowHeights = new int[rows]; + this.panelSize = panel.getSize(); + this.panel.addComponentListener(new ComponentListener() { + + @Override + public void componentShown(ComponentEvent arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void componentResized(ComponentEvent arg0) { +// Dimension size = panelSize; + panelSize = panel.getSize(); + for (ResizeableMouseListener rml : allRmls) { + rml.didResized(); + } + } + + @Override + public void componentMoved(ComponentEvent arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void componentHidden(ComponentEvent arg0) { + // TODO Auto-generated method stub + + } + }); + } + + + public void add(JComponent comp, int x, int y, int width, int height, int anchor, int fill) { + makeResizeable(comp, x, y, width, height); + SwingUtil.addComponent(panel, gbl, comp, x, y, width, height, 1.0, 1.0, anchor, fill); + + } + private void makeResizeable(JComponent comp, int x, int y, int width, int height) { + HashMap> oppositeNeighbours = new HashMap>(); + oppositeNeighbours.put(SwingConstants.NORTH, ResizeableMouseListener.copy(this.compByYEnd.get(y))); + oppositeNeighbours.put(SwingConstants.SOUTH, ResizeableMouseListener.copy(this.compByYStart.get(y + height))); + oppositeNeighbours.put(SwingConstants.WEST, ResizeableMouseListener.copy(this.compByXEnd.get(x))); + oppositeNeighbours.put(SwingConstants.EAST, ResizeableMouseListener.copy(this.compByXStart.get(x + width))); + HashMap> inlineNeighbours = new HashMap>(); + inlineNeighbours.put(SwingConstants.NORTH, ResizeableMouseListener.copy(this.compByYStart.get(y))); + inlineNeighbours.put(SwingConstants.SOUTH, ResizeableMouseListener.copy(this.compByYEnd.get(y + height))); + inlineNeighbours.put(SwingConstants.WEST, ResizeableMouseListener.copy(this.compByXStart.get(x))); + inlineNeighbours.put(SwingConstants.EAST, ResizeableMouseListener.copy(this.compByXEnd.get(x + width))); + + + ResizeableMouseListener rml = new ResizeableMouseListener(comp, 6, inlineNeighbours, oppositeNeighbours, gbl); + this.allRmls.add(rml); + addCompToMap(rml, x, y, width, height); + } + + + + public JPanel asJPanel(){ + return this.panel; + } + + private void addCompToMap(ResizeableMouseListener rml, int x, int y, int width, int height){ + addCompToMap(compByXStart, rml, x); + addCompToMap(compByYStart, rml, y); + addCompToMap(compByXEnd, rml, x + width); + addCompToMap(compByYEnd, rml, y + height); + + } + + private void addCompToMap(HashMap> map, ResizeableMouseListener comp, int pos){ + if(!map.containsKey(pos)){ + map.put(pos, new ArrayList()); + } + map.get(pos).add(comp); + } + +// private class RMLPosition { +// ResizeableMouseListener rml; +// int x; +// int y; +// int w; +// int h; +// public RMLPosition(ResizeableMouseListener rml, int x, int y, int w, int h){ +// this.rml = rml; +// this.x = x; +// this.y = y; +// this.w = w; +// this.h = h; +// +// } +// } +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/buttons/AbstractDropDownButton.java b/src/main/java/com/github/oxygenPlugins/common/gui/buttons/AbstractDropDownButton.java new file mode 100644 index 0000000..f1ed4b4 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/buttons/AbstractDropDownButton.java @@ -0,0 +1,19 @@ +package com.github.oxygenPlugins.common.gui.buttons; + +import javax.swing.Icon; +import javax.swing.JMenuItem; +import javax.swing.JPanel; + +public abstract class AbstractDropDownButton extends JPanel{ + + private static final long serialVersionUID = -8884841472288234500L; + + public abstract void addMenuItem(JMenuItem item); + public abstract void removeAllMenuItems(); + + public abstract void setIcon(Icon icon); + + public abstract void addSeparator(String title); + public abstract void addSeparator(); + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/buttons/DefaultAction.java b/src/main/java/com/github/oxygenPlugins/common/gui/buttons/DefaultAction.java new file mode 100644 index 0000000..e62b6ee --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/buttons/DefaultAction.java @@ -0,0 +1,46 @@ +package com.github.oxygenPlugins.common.gui.buttons; + +import java.awt.event.ActionEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.Action; + +public abstract class DefaultAction implements Action { + + @Override + public abstract void actionPerformed(ActionEvent arg0); + + @Override + public void addPropertyChangeListener(PropertyChangeListener listener) { + + } + + @Override + public Object getValue(String key) { + return null; + } + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public void putValue(String key, Object value) { + // TODO Auto-generated method stub + + } + + @Override + public void removePropertyChangeListener(PropertyChangeListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public void setEnabled(boolean b) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/buttons/DropDownButton.java b/src/main/java/com/github/oxygenPlugins/common/gui/buttons/DropDownButton.java new file mode 100644 index 0000000..5643a08 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/buttons/DropDownButton.java @@ -0,0 +1,218 @@ +package com.github.oxygenPlugins.common.gui.buttons; + +import java.awt.Component; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; + +import javax.swing.Box; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.JSeparator; + +import com.github.oxygenPlugins.common.gui.images.IconMap; +import com.github.oxygenPlugins.common.gui.swing.SwingUtil; + +public class DropDownButton extends AbstractDropDownButton implements MouseMotionListener { + + private static final long serialVersionUID = 6383094467766824925L; + + private final GridBagLayout gbl = new GridBagLayout(); + private final Button button; + private final JPopupMenu menuBar; + private final ArrayList items = new ArrayList(); + private JMenuItem selectedMItem; + + + private final Icon selectIcon = IconMap.ICONS.getIcon(14, 22); + + private int mouseX = -1; + + private int mouseY = -1; + + private abstract class Button extends JButton implements MouseListener{ + private static final long serialVersionUID = -3718955415293253222L; + private final GridBagLayout btnGbl = new GridBagLayout(); + private final JLabel btnLabel = new JLabel(); + private JSeparator separator = new JSeparator(JSeparator.VERTICAL); + private Component invSeparator = Box.createHorizontalStrut(2); + private JLabel menuLabel; + private _DropDownButtonAction action = null; + public Button() { + super(); + this.setLayout(btnGbl); + + File arrowIcon = new File("icons/arrow.gif"); + menuLabel = new JLabel(); + try { + menuLabel.setIcon(IconMap.getIcon(arrowIcon)); + } catch (IOException e) { + menuLabel.setIcon(IconMap.ICONS.getIcon(12, 22)); + } + + this.addMouseListener(this); + this.removeAll(); + SwingUtil.addComponent(this, btnGbl, btnLabel, 0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH); + hideSeparator(); + SwingUtil.addComponent(this, btnGbl, menuLabel, 2, 0, 1, 1, 1.0, 1.0, GridBagConstraints.EAST, GridBagConstraints.BOTH); + + + } + + private void hideSeparator(){ + this.remove(separator); + SwingUtil.addComponent(this, btnGbl, invSeparator, 1, 0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.VERTICAL); + this.updateUI(); + } + private void showSeparator(){ + this.remove(invSeparator); + SwingUtil.addComponent(this, btnGbl, separator, 1, 0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.VERTICAL); + this.updateUI(); + } + + + @Override + public void setIcon(Icon icon) { + if(btnLabel != null){ + btnLabel.setIcon(icon); + } + } + + public void action(MouseEvent e){ + if(this.action != null){ + action.action(e); + } + }; + + public abstract void popupMenu(MouseEvent e); + + @Override + public void mouseClicked(MouseEvent e) { + Component comp = e.getComponent().getComponentAt(mouseX, mouseY); + if(comp == this.btnLabel){ + button.action(e); + } else if (comp == this.menuLabel){ + button.popupMenu(e); + } else if (comp == this.separator){ + int center = comp.getWidth() / 2; + int xOnSep = mouseX - comp.getX(); + if(xOnSep < center){ + button.action(e); + } else { + button.popupMenu(e); + } + } + } + + @Override + public void mouseEntered(MouseEvent e) { + button.showSeparator(); + } + + @Override + public void mouseExited(MouseEvent e) { + button.hideSeparator(); + } + + @Override + public void mousePressed(MouseEvent e) {} + + @Override + public void mouseReleased(MouseEvent e) {} + + public void addActionListener(_DropDownButtonAction action) { + this.action = action; + } + } + + + public DropDownButton(_DropDownButtonAction action) { + this.setLayout(gbl); + this.menuBar = new JPopupMenu(); + this.button = new Button() { + /** + * + */ + private static final long serialVersionUID = 8097277545011108849L; + + @Override + public void popupMenu(MouseEvent e) { + int x = this.getX(); + int y = this.getY() + this.getHeight(); + updateItems(); + menuBar.show(DropDownButton.this, x, y); + } + }; + this.button.addActionListener(action); + + this.button.addMouseMotionListener(this); + + + + SwingUtil.addComponent(this, gbl, button, 0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH); + } + + private void updateItems(){ + for (JMenuItem item : items) { + item.setEnabled(item.isEnabled()); + } + } + + @Override + public void addMenuItem(JMenuItem item){ + this.items.add(item); + this.menuBar.add(item); + } + + @Override + public void addSeparator() { + this.addSeparator(""); + } + + @Override + public void addSeparator(String title) { + JSeparator sep = new JSeparator(); + this.menuBar.add(sep); + } + + @Override + public void setIcon(Icon icon) { + button.setIcon(icon); + } + + protected void setSelectedItem(JMenuItem item){ + if(selectedMItem != null){ + selectedMItem.setIcon(null); + } + selectedMItem = item; + item.setIcon(selectIcon); + DropDownButton.this.repaint(); + } + + + @Override + public void mouseMoved(MouseEvent me) { + this.mouseX = me.getX(); + this.mouseY = me.getY(); + + } + + @Override + public void mouseDragged(MouseEvent arg0) {} + + @Override + public void removeAllMenuItems() { +// for (JMenuItem item : this.items) { +// this.menuBar.remove(item); +// } + this.menuBar.removeAll(); + } +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/buttons/_DropDownButtonAction.java b/src/main/java/com/github/oxygenPlugins/common/gui/buttons/_DropDownButtonAction.java new file mode 100644 index 0000000..f3f6663 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/buttons/_DropDownButtonAction.java @@ -0,0 +1,7 @@ +package com.github.oxygenPlugins.common.gui.buttons; + +import java.awt.event.MouseEvent; + +public interface _DropDownButtonAction { + void action(MouseEvent e); +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/images/GifDecoder.java b/src/main/java/com/github/oxygenPlugins/common/gui/images/GifDecoder.java new file mode 100644 index 0000000..a43dde4 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/images/GifDecoder.java @@ -0,0 +1,806 @@ +package com.github.oxygenPlugins.common.gui.images; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferInt; +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; + +/** + * Class GifDecoder - Decodes a GIF file into one or more frames.
+ * + *
+ *  Example:
+ *     GifDecoder d = new GifDecoder();
+ *     d.read("sample.gif");
+ *     int n = d.getFrameCount();
+ *     for (int i = 0; i < n; i++) {
+ *        BufferedImage frame = d.getFrame(i);  // frame i
+ *        int t = d.getDelay(i);  // display duration of frame in milliseconds
+ *        // do something with frame
+ *     }
+ * 
+ * + * No copyright asserted on the source code of this class. May be used for any + * purpose, however, refer to the Unisys LZW patent for any additional + * restrictions. Please forward any corrections to kweiner@fmsware.com. + * + * @author Kevin Weiner, FM Software; LZW decoder adapted from John Cristy's + * ImageMagick. + * @version 1.03 November 2003 + * + */ + +public class GifDecoder { + + /** + * File read status: No errors. + */ + public static final int STATUS_OK = 0; + + /** + * File read status: Error decoding file (may be partially decoded) + */ + public static final int STATUS_FORMAT_ERROR = 1; + + /** + * File read status: Unable to open source. + */ + public static final int STATUS_OPEN_ERROR = 2; + + protected BufferedInputStream in; + + protected int status; + + protected int width; // full image width + + protected int height; // full image height + + protected boolean gctFlag; // global color table used + + protected int gctSize; // size of global color table + + protected int loopCount = 1; // iterations; 0 = repeat forever + + protected int[] gct; // global color table + + protected int[] lct; // local color table + + protected int[] act; // active color table + + protected int bgIndex; // background color index + + protected int bgColor; // background color + + protected int lastBgColor; // previous bg color + + protected int pixelAspect; // pixel aspect ratio + + protected boolean lctFlag; // local color table flag + + protected boolean interlace; // interlace flag + + protected int lctSize; // local color table size + + protected int ix, iy, iw, ih; // current image rectangle + + protected Rectangle lastRect; // last image rect + + protected BufferedImage image; // current frame + + protected BufferedImage lastImage; // previous frame + + protected byte[] block = new byte[256]; // current data block + + protected int blockSize = 0; // block size + + // last graphic control extension info + protected int dispose = 0; + + // 0=no action; 1=leave in place; 2=restore to bg; 3=restore to prev + protected int lastDispose = 0; + + protected boolean transparency = false; // use transparent color + + protected int delay = 0; // delay in milliseconds + + protected int transIndex; // transparent color index + + protected static final int MaxStackSize = 4096; + + // max decoder pixel stack size + + // LZW decoder working arrays + protected short[] prefix; + + protected byte[] suffix; + + protected byte[] pixelStack; + + protected byte[] pixels; + + @SuppressWarnings("rawtypes") +protected ArrayList frames; // frames read from current file + + protected int frameCount; + + static class GifFrame { + public GifFrame(BufferedImage im, int del) { + image = im; + delay = del; + } + + public BufferedImage image; + + public int delay; + } + + /** + * Gets display duration for specified frame. + * + * @param n + * int index of frame + * @return delay in milliseconds + */ + public int getDelay(int n) { + // + delay = -1; + if ((n >= 0) && (n < frameCount)) { + delay = ((GifFrame) frames.get(n)).delay; + } + return delay; + } + + /** + * Gets the number of frames read from file. + * + * @return frame count + */ + public int getFrameCount() { + return frameCount; + } + + /** + * Gets the first (or only) image read. + * + * @return BufferedImage containing first frame, or null if none. + */ + public BufferedImage getImage() { + return getFrame(0); + } + + /** + * Gets the "Netscape" iteration count, if any. A count of 0 means repeat + * indefinitiely. + * + * @return iteration count if one was specified, else 1. + */ + public int getLoopCount() { + return loopCount; + } + + /** + * Creates new frame image from current data (and previous frames as specified + * by their disposition codes). + */ + protected void setPixels() { + // expose destination image's pixels as int array + int[] dest = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); + + // fill in starting image contents based on last image's dispose code + if (lastDispose > 0) { + if (lastDispose == 3) { + // use image before last + int n = frameCount - 2; + if (n > 0) { + lastImage = getFrame(n - 1); + } else { + lastImage = null; + } + } + + if (lastImage != null) { + int[] prev = ((DataBufferInt) lastImage.getRaster().getDataBuffer()).getData(); + System.arraycopy(prev, 0, dest, 0, width * height); + // copy pixels + + if (lastDispose == 2) { + // fill last image rect area with background color + Graphics2D g = image.createGraphics(); + Color c = null; + if (transparency) { + c = new Color(0, 0, 0, 0); // assume background is transparent + } else { + c = new Color(lastBgColor); // use given background color + } + g.setColor(c); + g.setComposite(AlphaComposite.Src); // replace area + g.fill(lastRect); + g.dispose(); + } + } + } + + // copy each source line to the appropriate place in the destination + int pass = 1; + int inc = 8; + int iline = 0; + for (int i = 0; i < ih; i++) { + int line = i; + if (interlace) { + if (iline >= ih) { + pass++; + switch (pass) { + case 2: + iline = 4; + break; + case 3: + iline = 2; + inc = 4; + break; + case 4: + iline = 1; + inc = 2; + } + } + line = iline; + iline += inc; + } + line += iy; + if (line < height) { + int k = line * width; + int dx = k + ix; // start of line in dest + int dlim = dx + iw; // end of dest line + if ((k + width) < dlim) { + dlim = k + width; // past dest edge + } + int sx = i * iw; // start of line in source + while (dx < dlim) { + // map color and insert in destination + int index = ((int) pixels[sx++]) & 0xff; + int c = act[index]; + if (c != 0) { + dest[dx] = c; + } + dx++; + } + } + } + } + + /** + * Gets the image contents of frame n. + * + * @return BufferedImage representation of frame, or null if n is invalid. + */ + public BufferedImage getFrame(int n) { + BufferedImage im = null; + if ((n >= 0) && (n < frameCount)) { + im = ((GifFrame) frames.get(n)).image; + } + return im; + } + + /** + * Gets image size. + * + * @return GIF image dimensions + */ + public Dimension getFrameSize() { + return new Dimension(width, height); + } + + /** + * Reads GIF image from stream + * + * @param BufferedInputStream + * containing GIF file. + * @return read status code (0 = no errors) + */ + public int read(BufferedInputStream is) { + init(); + if (is != null) { + in = is; + readHeader(); + if (!err()) { + readContents(); + if (frameCount < 0) { + status = STATUS_FORMAT_ERROR; + } + } + } else { + status = STATUS_OPEN_ERROR; + } + try { + is.close(); + } catch (IOException e) { + } + return status; + } + + /** + * Reads GIF image from stream + * + * @param InputStream + * containing GIF file. + * @return read status code (0 = no errors) + */ + public int read(InputStream is) { + init(); + if (is != null) { + if (!(is instanceof BufferedInputStream)) + is = new BufferedInputStream(is); + in = (BufferedInputStream) is; + readHeader(); + if (!err()) { + readContents(); + if (frameCount < 0) { + status = STATUS_FORMAT_ERROR; + } + } + } else { + status = STATUS_OPEN_ERROR; + } + try { + is.close(); + } catch (IOException e) { + } + return status; + } + + /** + * Reads GIF file from specified file/URL source (URL assumed if name contains + * ":/" or "file:") + * + * @param name + * String containing source + * @return read status code (0 = no errors) + */ + public int read(String name) { + status = STATUS_OK; + try { + name = name.trim().toLowerCase(); + if ((name.indexOf("file:") >= 0) || (name.indexOf(":/") > 0)) { + URL url = new URL(name); + in = new BufferedInputStream(url.openStream()); + } else { + in = new BufferedInputStream(new FileInputStream(name)); + } + status = read(in); + } catch (IOException e) { + status = STATUS_OPEN_ERROR; + } + + return status; + } + + /** + * Decodes LZW image data into pixel array. Adapted from John Cristy's + * ImageMagick. + */ + protected void decodeImageData() { + int NullCode = -1; + int npix = iw * ih; + int available, clear, code_mask, code_size, end_of_information, in_code, old_code, bits, code, count, i, datum, data_size, first, top, bi, pi; + + if ((pixels == null) || (pixels.length < npix)) { + pixels = new byte[npix]; // allocate new pixel array + } + if (prefix == null) + prefix = new short[MaxStackSize]; + if (suffix == null) + suffix = new byte[MaxStackSize]; + if (pixelStack == null) + pixelStack = new byte[MaxStackSize + 1]; + + // Initialize GIF data stream decoder. + + data_size = read(); + clear = 1 << data_size; + end_of_information = clear + 1; + available = clear + 2; + old_code = NullCode; + code_size = data_size + 1; + code_mask = (1 << code_size) - 1; + for (code = 0; code < clear; code++) { + prefix[code] = 0; + suffix[code] = (byte) code; + } + + // Decode GIF pixel stream. + + datum = bits = count = first = top = pi = bi = 0; + + for (i = 0; i < npix;) { + if (top == 0) { + if (bits < code_size) { + // Load bytes until there are enough bits for a code. + if (count == 0) { + // Read a new data block. + count = readBlock(); + if (count <= 0) + break; + bi = 0; + } + datum += (((int) block[bi]) & 0xff) << bits; + bits += 8; + bi++; + count--; + continue; + } + + // Get the next code. + + code = datum & code_mask; + datum >>= code_size; + bits -= code_size; + + // Interpret the code + + if ((code > available) || (code == end_of_information)) + break; + if (code == clear) { + // Reset decoder. + code_size = data_size + 1; + code_mask = (1 << code_size) - 1; + available = clear + 2; + old_code = NullCode; + continue; + } + if (old_code == NullCode) { + pixelStack[top++] = suffix[code]; + old_code = code; + first = code; + continue; + } + in_code = code; + if (code == available) { + pixelStack[top++] = (byte) first; + code = old_code; + } + while (code > clear) { + pixelStack[top++] = suffix[code]; + code = prefix[code]; + } + first = ((int) suffix[code]) & 0xff; + + // Add a new string to the string table, + + if (available >= MaxStackSize) + break; + pixelStack[top++] = (byte) first; + prefix[available] = (short) old_code; + suffix[available] = (byte) first; + available++; + if (((available & code_mask) == 0) && (available < MaxStackSize)) { + code_size++; + code_mask += available; + } + old_code = in_code; + } + + // Pop a pixel off the pixel stack. + + top--; + pixels[pi++] = pixelStack[top]; + i++; + } + + for (i = pi; i < npix; i++) { + pixels[i] = 0; // clear missing pixels + } + + } + + /** + * Returns true if an error was encountered during reading/decoding + */ + protected boolean err() { + return status != STATUS_OK; + } + + /** + * Initializes or re-initializes reader + */ + @SuppressWarnings("rawtypes") +protected void init() { + status = STATUS_OK; + frameCount = 0; + frames = new ArrayList(); + gct = null; + lct = null; + } + + /** + * Reads a single byte from the input stream. + */ + protected int read() { + int curByte = 0; + try { + curByte = in.read(); + } catch (IOException e) { + status = STATUS_FORMAT_ERROR; + } + return curByte; + } + + /** + * Reads next variable length block from input. + * + * @return number of bytes stored in "buffer" + */ + protected int readBlock() { + blockSize = read(); + int n = 0; + if (blockSize > 0) { + try { + int count = 0; + while (n < blockSize) { + count = in.read(block, n, blockSize - n); + if (count == -1) + break; + n += count; + } + } catch (IOException e) { + } + + if (n < blockSize) { + status = STATUS_FORMAT_ERROR; + } + } + return n; + } + + /** + * Reads color table as 256 RGB integer values + * + * @param ncolors + * int number of colors to read + * @return int array containing 256 colors (packed ARGB with full alpha) + */ + protected int[] readColorTable(int ncolors) { + int nbytes = 3 * ncolors; + int[] tab = null; + byte[] c = new byte[nbytes]; + int n = 0; + try { + n = in.read(c); + } catch (IOException e) { + } + if (n < nbytes) { + status = STATUS_FORMAT_ERROR; + } else { + tab = new int[256]; // max size to avoid bounds checks + int i = 0; + int j = 0; + while (i < ncolors) { + int r = ((int) c[j++]) & 0xff; + int g = ((int) c[j++]) & 0xff; + int b = ((int) c[j++]) & 0xff; + tab[i++] = 0xff000000 | (r << 16) | (g << 8) | b; + } + } + return tab; + } + + /** + * Main file parser. Reads GIF content blocks. + */ + protected void readContents() { + // read GIF file content blocks + boolean done = false; + while (!(done || err())) { + int code = read(); + switch (code) { + + case 0x2C: // image separator + readImage(); + break; + + case 0x21: // extension + code = read(); + switch (code) { + case 0xf9: // graphics control extension + readGraphicControlExt(); + break; + + case 0xff: // application extension + readBlock(); + String app = ""; + for (int i = 0; i < 11; i++) { + app += (char) block[i]; + } + if (app.equals("NETSCAPE2.0")) { + readNetscapeExt(); + } else + skip(); // don't care + break; + + default: // uninteresting extension + skip(); + } + break; + + case 0x3b: // terminator + done = true; + break; + + case 0x00: // bad byte, but keep going and see what happens + break; + + default: + status = STATUS_FORMAT_ERROR; + } + } + } + + /** + * Reads Graphics Control Extension values + */ + protected void readGraphicControlExt() { + read(); // block size + int packed = read(); // packed fields + dispose = (packed & 0x1c) >> 2; // disposal method + if (dispose == 0) { + dispose = 1; // elect to keep old image if discretionary + } + transparency = (packed & 1) != 0; + delay = readShort() * 10; // delay in milliseconds + transIndex = read(); // transparent color index + read(); // block terminator + } + + /** + * Reads GIF file header information. + */ + protected void readHeader() { + String id = ""; + for (int i = 0; i < 6; i++) { + id += (char) read(); + } + if (!id.startsWith("GIF")) { + status = STATUS_FORMAT_ERROR; + return; + } + + readLSD(); + if (gctFlag && !err()) { + gct = readColorTable(gctSize); + bgColor = gct[bgIndex]; + } + } + + /** + * Reads next frame image + */ + @SuppressWarnings("unchecked") +protected void readImage() { + ix = readShort(); // (sub)image position & size + iy = readShort(); + iw = readShort(); + ih = readShort(); + + int packed = read(); + lctFlag = (packed & 0x80) != 0; // 1 - local color table flag + interlace = (packed & 0x40) != 0; // 2 - interlace flag + // 3 - sort flag + // 4-5 - reserved + lctSize = 2 << (packed & 7); // 6-8 - local color table size + + if (lctFlag) { + lct = readColorTable(lctSize); // read table + act = lct; // make local table active + } else { + act = gct; // make global table active + if (bgIndex == transIndex) + bgColor = 0; + } + int save = 0; + if (transparency) { + save = act[transIndex]; + act[transIndex] = 0; // set transparent color if specified + } + + if (act == null) { + status = STATUS_FORMAT_ERROR; // no color table defined + } + + if (err()) + return; + + decodeImageData(); // decode pixel data + skip(); + + if (err()) + return; + + frameCount++; + + // create new image to receive frame data + image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE); + + setPixels(); // transfer pixel data to image + + frames.add(new GifFrame(image, delay)); // add image to frame list + + if (transparency) { + act[transIndex] = save; + } + resetFrame(); + + } + + /** + * Reads Logical Screen Descriptor + */ + protected void readLSD() { + + // logical screen size + width = readShort(); + height = readShort(); + + // packed fields + int packed = read(); + gctFlag = (packed & 0x80) != 0; // 1 : global color table flag + // 2-4 : color resolution + // 5 : gct sort flag + gctSize = 2 << (packed & 7); // 6-8 : gct size + + bgIndex = read(); // background color index + pixelAspect = read(); // pixel aspect ratio + } + + /** + * Reads Netscape extenstion to obtain iteration count + */ + protected void readNetscapeExt() { + do { + readBlock(); + if (block[0] == 1) { + // loop count sub-block + int b1 = ((int) block[1]) & 0xff; + int b2 = ((int) block[2]) & 0xff; + loopCount = (b2 << 8) | b1; + } + } while ((blockSize > 0) && !err()); + } + + /** + * Reads next 16-bit value, LSB first + */ + protected int readShort() { + // read 16-bit value, LSB first + return read() | (read() << 8); + } + + /** + * Resets frame state for reading next image. + */ + @SuppressWarnings("unused") +protected void resetFrame() { + lastDispose = dispose; + lastRect = new Rectangle(ix, iy, iw, ih); + lastImage = image; + lastBgColor = bgColor; + int dispose = 0; + boolean transparency = false; + int delay = 0; + lct = null; + } + + /** + * Skips variable length blocks up to and including next zero length block. + */ + protected void skip() { + do { + readBlock(); + } while ((blockSize > 0) && !err()); + } +} \ No newline at end of file diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/images/IconMap.java b/src/main/java/com/github/oxygenPlugins/common/gui/images/IconMap.java new file mode 100644 index 0000000..c016585 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/images/IconMap.java @@ -0,0 +1,264 @@ +package com.github.oxygenPlugins.common.gui.images; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Point; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Set; + +import javax.imageio.ImageIO; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileSystemView; + +public final class IconMap { + + private final BufferedImage image; + + public static IconMap ICONS; + public static File BASE_DIR = new File("."); + + public IconMap(String resource) throws IOException { + this(new Object().getClass().getResourceAsStream(resource)); + } + + public IconMap(File imageMapFile) throws FileNotFoundException, IOException { + this(new FileInputStream(imageMapFile.isAbsolute() ? imageMapFile + : new File(BASE_DIR, imageMapFile.getPath()))); + } + + private IconMap(InputStream in) throws IOException { + if (in != null) { + GifDecoder decoder = new GifDecoder(); + decoder.read(in); + this.image = decoder.getImage(); + in.close(); + } else { + this.image = null; + } + } + + public IconMap() throws IOException { + this(resMapPath); + } + + private static String resMapPath = "/icons/diagona_my.gif"; + + private static final int intervallX = 23; + private static final int intervallY = 26; + + private static final int bigIconWidth = 17; + private static final int bigIconHeight = 18; + private static final int iconOffsetX = 2; + private static final int iconOffsetY = 3; + private static final int smallIconWidth = 16; + private static final int smallIconHeight = 18; + private static final int smallIconOffsetX = 3; + private static final int smallIconOffsetY = 6; + + // ICONS + public static final Point NEUTRAL = new Point(12, 2); + public static final Point DIAGNOSTIC = new Point(14, 2); + + public static final Point MESSAGE_GROUP_FAILED = new Point(0, 10); + public static final Point MESSAGE_GROUP_SUCCEDED = new Point(2, 10); + + public static final Point MESSAGE_WARNING = new Point(6, 15); + public static final Point MESSAGE_ERROR = new Point(0, 15); + public static final Point MESSAGE_FATAL_ERROR = new Point(0, 20); + public static final Point MESSAGE_INFO = new Point(16, 15); + public static final Point QUICKFIX_ADD = new Point(4, 10); + public static final Point QUICKFIX_DELETE = new Point(0, 10); + public static final Point QUICKFIX_REPLACE = new Point(2, 12); + public static final Point QUICKFIX_STRING_REPLACE = new Point(14, 1); + + public static final Point USER_ENTRY = new Point(16, 1); + + public static final Point NOICON = new Point(14, 20); + public static final Point QUICKFIX_HAS_PARAM = new Point(18, 18); + public static final Point USER_ENTRY_QUEST = new Point(11, 14); + public static final Point QUICKFIX_HAS_LINK = new Point(8, 16); + + public static ImageIcon getIcon(String source) throws IOException{ + InputStream is = new Object().getClass().getResourceAsStream(source); + BufferedImage image = null; + if(is != null){ + image = ImageIO.read(is); + } + if (image == null) + throw new IOException("Format is not supported or source " + source + " is not available."); + return new ImageIcon(image); + + } + + public static ImageIcon getIcon(File file) throws IOException { + BufferedImage image = null; + if (!file.isAbsolute()) { + file = new File(BASE_DIR, file.getPath()); + } + image = ImageIO.read(file); + + if (image == null) + throw new IOException("Format is not supported or source " + file.toString() + " is not available."); + return new ImageIcon(image); + + } + + public static ImageIcon getIcon(URI path) throws IOException { + return getIcon(new File(path)); + } + + public ImageIcon getIcon(Point p) { + return getIcon(p.x, p.y); + } + + public ImageIcon getIcon(int x, int y) { + return getIcon(x, y, x % 2 == 0); + } + + public ImageIcon getIcon(int x, int y, boolean small) { + + int xOffset = small ? smallIconOffsetX : iconOffsetX; + int yOffset = small ? smallIconOffsetY : iconOffsetY; + int w = small ? smallIconWidth : bigIconWidth; + int h = small ? smallIconHeight : bigIconHeight; + Image img = ImageUtils.subimage(image, x * intervallX + xOffset, y + * intervallY + yOffset, w, h); + + return new ImageIcon(img); + } + + private static final LinkedHashMap iconStore = new LinkedHashMap(); + private static final int ICON_STORE_COUNT = 20; + + private static void storeIcon(String extension, Icon icon) { + iconStore.put(extension, icon); + Object[] keys = iconStore.keySet().toArray(); + int oversize = keys.length - ICON_STORE_COUNT; + for (int i = 0; i < oversize; i++) { + iconStore.remove(keys[i]); + } + } + + public static Icon getSystemIcon(File file){ + Icon ico; +// if(System.getProperty("os.name").toLowerCase().contains("mac")){ +// JFileChooser jf = new JFileChooser(); +// ico = jf.getUI().getFileView(jf).getIcon(file); +// } else { + ico = FileSystemView.getFileSystemView().getSystemIcon(file); +// } + return ico; + } + + public static Icon getSystemIconByExt(String ext) throws IOException { + if(iconStore.containsKey(ext)){ + + return iconStore.get(ext); + + } else { + + File temp = File.createTempFile("openDocs", "." + ext); + temp.createNewFile(); + Icon ico = getSystemIcon(temp); + storeIcon(ext, ico); + temp.delete(); + return ico; + + } + } + + public static Icon filter(Icon icon) { + return filter(icon, 0.5); + } + + public static Icon filter(Icon icon, double fac) { + if(fac == 1.0) + return icon; + return filter(icon, fac, fac, fac, fac); + } + + public static Icon filter(Icon icon, Double[] facs) { + if(facs == null) + return icon; + return filter(icon, facs[0], facs[1], facs[2], facs[3]); + } + + public static Icon filter(Icon icon, double rFac, double gFac, double bFac, + double aFac) { + + BufferedImage bi = new BufferedImage(icon.getIconWidth(), + icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics g = bi.createGraphics(); + // paint the Icon to the BufferedImage. + icon.paintIcon(null, g, 0, 0); + g.dispose(); + + for (int i = 0; i < bi.getHeight(); i++) { + for (int j = 0; j < bi.getWidth(); j++) { + int rgb = bi.getRGB(j, i); + Color c = new Color(rgb, true); + Color nc = new Color(filter(c.getRed(), rFac), filter( + c.getGreen(), gFac), filter(c.getBlue(), bFac), filter( + c.getAlpha(), aFac)); + bi.setRGB(j, i, nc.getRGB()); + } + } + return new ImageIcon(bi); + } + + private static int filter(int colorValue, double factor) { + double newDouble = colorValue * factor; + + if (newDouble >= 255.0) { + return 255; + } + + return (int) Math.round(newDouble); + } + + private static Icon resize(Icon icon, int width, int height) { + int oWidth = icon.getIconWidth(); + int oHeight = icon.getIconHeight(); + int nWidth = oWidth > width ? oWidth : width; + int nHeight = oHeight > height ? oHeight : height; + + int x = (nWidth - width) / 2; + int y = (nHeight - height) / 2; + + BufferedImage bi = new BufferedImage(nWidth, nHeight, + BufferedImage.TYPE_INT_ARGB); + Graphics g = bi.createGraphics(); + // paint the Icon to the BufferedImage. + icon.paintIcon(null, g, x, y); + g.dispose(); + return new ImageIcon(bi); + } + + public static Icon[] adjustIcons(Icon[] icons) { + int mWidth = 0; + int mHeight = 0; + for (Icon icon : icons) { + mWidth = mWidth > icon.getIconWidth() ? mWidth : icon + .getIconWidth(); + mHeight = mHeight > icon.getIconHeight() ? mHeight : icon + .getIconHeight(); + } + Icon[] newIcons = new Icon[icons.length]; + for (int i = 0; i < icons.length; i++) { + newIcons[i] = resize(icons[i], mWidth, mHeight); + } + return newIcons; + } + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/images/ImageUtils.java b/src/main/java/com/github/oxygenPlugins/common/gui/images/ImageUtils.java new file mode 100644 index 0000000..fed9f0b --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/images/ImageUtils.java @@ -0,0 +1,161 @@ +/* + * Copyright 2008-2011, David Karnok + * The file is part of the Open Imperium Galactica project. + * + * The code should be distributed under the LGPL license. + * See http://www.gnu.org/licenses/lgpl.html for details. + */ +package com.github.oxygenPlugins.common.gui.images; + +import java.awt.image.BufferedImage; + +/** + * Image manipulation utilities. + * + * @author akarnokd + */ +public final class ImageUtils { + /** Use subimage or separate image. */ + private static final boolean SUBIMAGE = false; + + /** Private constructor. */ + private ImageUtils() { + // private class + } + + /** + * Returns a subimage of the given main image. If the sub-image tends to be + * smaller in area then the original image, a new buffered image is returned + * instead of the shared sub image + * + * @param src + * the source image. + * @param x + * the x coordinate + * @param y + * the y coordinate + * @param w + * the width + * @param h + * the height + * @return the extracted sub-image + */ + @SuppressWarnings("unused") + public static BufferedImage subimage(BufferedImage src, int x, int y, + int w, int h) { + if (!SUBIMAGE /* && w * h * 16 < src.getWidth() * src.getHeight() */) { + return newSubimage(src, x, y, w, h); + } + return src.getSubimage(x, y, w, h); + } + + /** + * Returns an independent subimage of the given main image. copying data + * from the original image. + * + * @param src + * the source image. + * @param x + * the x coordinate + * @param y + * the y coordinate + * @param w + * the width + * @param h + * the height + * @return the extracted sub-image + */ + public static BufferedImage newSubimage(BufferedImage src, int x, int y, + int w, int h) { + BufferedImage bimg = new BufferedImage(w, h, + BufferedImage.TYPE_INT_ARGB); + int[] tmp = new int[w * h]; + src.getRGB(x, y, w, h, tmp, 0, w); + bimg.setRGB(0, 0, w, h, tmp, 0, w); + return bimg; + } + + /** + * Recolor a given default tile image. + * + * @param img + * the original image. + * @param newColor + * the new RGBA color. + * @return the new RGBA image + */ + public static BufferedImage recolor(BufferedImage img, int newColor) { + int[] pixels = new int[img.getWidth() * img.getHeight()]; + img.getRGB(0, 0, img.getWidth(), img.getHeight(), pixels, 0, + img.getWidth()); + for (int i = 0; i < pixels.length; i++) { + int c = pixels[i]; + if (c == 0xFF000000) { + pixels[i] = newColor; + } + } + BufferedImage result = new BufferedImage(img.getWidth(), + img.getHeight(), BufferedImage.TYPE_INT_ARGB); + result.setRGB(0, 0, img.getWidth(), img.getHeight(), pixels, 0, + img.getWidth()); + return result; + } + + /** + * Split the image into equally sized sub-images. + * + * @param img + * the image to split + * @param width + * the split width + * @return the array of images + */ + public static BufferedImage[] splitByWidth(BufferedImage img, int width) { + if (img.getWidth() > 0) { + BufferedImage[] result = new BufferedImage[(img.getWidth() + width - 1) + / width]; + int x = 0; + for (int i = 0; i < result.length; i++) { + int x2 = Math.min(x + width - 1, img.getWidth() - 1); + result[i] = newSubimage(img, x, 0, x2 - x + 1, img.getHeight()); + x += width; + } + return result; + } + return new BufferedImage[0]; + } + + /** + * Split the image into equally sized sub-images. + * + * @param img + * the image to split + * @param width + * the split width + * @param height + * the split height + * @return the array of array images, the first dimension are the image rows + */ + public static BufferedImage[][] split(BufferedImage img, int width, + int height) { + if (img.getWidth() > 0) { + + BufferedImage[][] result = new BufferedImage[(img.getHeight() + + height - 1) + / height][(img.getWidth() + width - 1) / width]; + int y = 0; + for (int j = 0; j < result.length; j++) { + int x = 0; + int y2 = Math.min(y + height - 1, img.getHeight() - 1); + for (int i = 0; i < result.length; i++) { + int x2 = Math.min(x + width - 1, img.getWidth() - 1); + result[j][i] = newSubimage(img, x, y, x2 - x + 1, y2 - y + + 1); + x += width; + } + y += height; + } + } + return new BufferedImage[0][]; + } +} \ No newline at end of file diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/images/PNGDecoder.java b/src/main/java/com/github/oxygenPlugins/common/gui/images/PNGDecoder.java new file mode 100644 index 0000000..edcdbb6 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/images/PNGDecoder.java @@ -0,0 +1,463 @@ +package com.github.oxygenPlugins.common.gui.images; +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): Alexandre Iline. + * + * The Original Software is the Jemmy library. + * The Initial Developer of the Original Software is Alexandre Iline. + * All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * + * + * $Id$ $Revision$ $Date$ + * + */ + + +import java.awt.AWTException; +import java.awt.Color; +import java.awt.Component; +import java.awt.HeadlessException; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.image.BufferedImage; +import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.zip.CRC32; +import java.util.zip.DataFormatException; +import java.util.zip.Deflater; +import java.util.zip.DeflaterOutputStream; +import java.util.zip.Inflater; + + + +/** + * Allows to load PNG graphical file. + * @author Alexandre Iline + */ +public class PNGDecoder extends Object { + + InputStream in; + + /** + * Constructs a PNGDecoder object. + * @param in input stream to read PNG image from. + */ + public PNGDecoder(InputStream in) { + this.in = in; + } + + byte read() throws IOException { + byte b = (byte)in.read(); + return(b); + } + + int readInt() throws IOException { + byte b[] = read(4); + return(((b[0]&0xff)<<24) + + ((b[1]&0xff)<<16) + + ((b[2]&0xff)<<8) + + ((b[3]&0xff))); + } + + byte[] read(int count) throws IOException { + byte[] result = new byte[count]; + for(int i = 0; i < count; i++) { + result[i] = read(); + } + return(result); + } + + boolean compare(byte[] b1, byte[] b2) { + if(b1.length != b2.length) { + return(false); + } + for(int i = 0; i < b1.length; i++) { + if(b1[i] != b2[i]) { + return(false); + } + } + return(true); + } + + void checkEquality(byte[] b1, byte[] b2) { + if(!compare(b1, b2)) { + throw(new RuntimeException("Format error")); + } + } + + /** + * Decodes image from an input stream passed into constructor. + * @return a BufferedImage object + * @throws IOException + */ + public BufferedImage decode() throws IOException { + + byte[] id = read(12); + checkEquality(id, new byte[] {-119, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13}); + + byte[] ihdr = read(4); + checkEquality(ihdr, "IHDR".getBytes()); + + int width = readInt(); + int height = readInt(); + + BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + + byte[] head = read(5); + int mode; + if(compare(head, new byte[]{1, 0, 0, 0, 0})) { + mode = PNGEncoder.BW_MODE; + } else if(compare(head, new byte[]{8, 0, 0, 0, 0})) { + mode = PNGEncoder.GREYSCALE_MODE; + } else if(compare(head, new byte[]{8, 2, 0, 0, 0})) { + mode = PNGEncoder.COLOR_MODE; + } else { + throw(new RuntimeException("Format error")); + } + + readInt();//!!crc + + int size = readInt(); + + byte[] idat = read(4); + checkEquality(idat, "IDAT".getBytes()); + + byte[] data = read(size); + + + Inflater inflater = new Inflater(); + inflater.setInput(data, 0, size); + + int color; + + try { + switch (mode) { + case PNGEncoder.BW_MODE: + { + int bytes = (int)(width / 8); + if((width % 8) != 0) { + bytes++; + } + byte colorset; + byte[] row = new byte[bytes]; + for (int y = 0; y < height; y++) { + inflater.inflate(new byte[1]); + inflater.inflate(row); + for (int x = 0; x < bytes; x++) { + colorset = row[x]; + for (int sh = 0; sh < 8; sh++) { + if(x * 8 + sh >= width) { + break; + } + if((colorset & 0x80) == 0x80) { + result.setRGB(x * 8 + sh, y, Color.white.getRGB()); + } else { + result.setRGB(x * 8 + sh, y, Color.black.getRGB()); + } + colorset <<= 1; + } + } + } + } + break; + case PNGEncoder.GREYSCALE_MODE: + { + byte[] row = new byte[width]; + for (int y = 0; y < height; y++) { + inflater.inflate(new byte[1]); + inflater.inflate(row); + for (int x = 0; x < width; x++) { + color = row[x]; + result.setRGB(x, y, (color << 16) + (color << 8) + color); + } + } + } + break; + case PNGEncoder.COLOR_MODE: + { + byte[] row = new byte[width * 3]; + for (int y = 0; y < height; y++) { + inflater.inflate(new byte[1]); + inflater.inflate(row); + for (int x = 0; x < width; x++) { + result.setRGB(x, y, + ((row[x * 3 + 0]&0xff) << 16) + + ((row[x * 3 + 1]&0xff) << 8) + + ((row[x * 3 + 2]&0xff))); + } + } + } + } + } catch(DataFormatException e) { + throw(new RuntimeException("ZIP error"+e)); + } + + readInt();//!!crc + readInt();//0 + + byte[] iend = read(4); + checkEquality(iend, "IEND".getBytes()); + + readInt();//!!crc + in.close(); + + return(result); + } + + /** + * Decodes image from file. + * @param fileName a file to read image from + * @return a BufferedImage instance. + */ + public static BufferedImage decode(String fileName) { + try { + return(new PNGDecoder(new FileInputStream(fileName)).decode()); + } catch(IOException e) { + throw(new RuntimeException("IOException during image reading"+ e)); + } + } + +} + +class PNGEncoder extends Object { + + /** black and white image mode. */ + public static final byte BW_MODE = 0; + /** grey scale image mode. */ + public static final byte GREYSCALE_MODE = 1; + /** full color image mode. */ + public static final byte COLOR_MODE = 2; + + OutputStream out; + CRC32 crc; + byte mode; + + /** public constructor of PNGEncoder class with greyscale mode by default. + * @param out output stream for PNG image format to write into + */ + public PNGEncoder(OutputStream out) { + this(out, GREYSCALE_MODE); + } + + /** public constructor of PNGEncoder class. + * @param out output stream for PNG image format to write into + * @param mode BW_MODE, GREYSCALE_MODE or COLOR_MODE + */ + public PNGEncoder(OutputStream out, byte mode) { + crc=new CRC32(); + this.out = out; + if (mode<0 || mode>2) + throw new IllegalArgumentException("Unknown color mode"); + this.mode = mode; + } + + void write(int i) throws IOException { + byte b[]={(byte)((i>>24)&0xff),(byte)((i>>16)&0xff),(byte)((i>>8)&0xff),(byte)(i&0xff)}; + write(b); + } + + void write(byte b[]) throws IOException { + out.write(b); + crc.update(b); + } + + /** main encoding method (stays blocked till encoding is finished). + * @param image BufferedImage to encode + * @throws IOException IOException + */ + public void encode(BufferedImage image) throws IOException { + int width = image.getWidth(null); + int height = image.getHeight(null); + final byte id[] = {-119, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13}; + write(id); + crc.reset(); + write("IHDR".getBytes()); + write(width); + write(height); + byte head[]=null; + switch (mode) { + case BW_MODE: head=new byte[]{1, 0, 0, 0, 0}; break; + case GREYSCALE_MODE: head=new byte[]{8, 0, 0, 0, 0}; break; + case COLOR_MODE: head=new byte[]{8, 2, 0, 0, 0}; break; + } + write(head); + write((int) crc.getValue()); + ByteArrayOutputStream compressed = new ByteArrayOutputStream(65536); + BufferedOutputStream bos = new BufferedOutputStream( new DeflaterOutputStream(compressed, new Deflater(9))); + int pixel; + int color; + int colorset; + switch (mode) { + case BW_MODE: + int rest=width%8; + int bytes=width/8; + for (int y=0;y> 16) & 0xff); + color+=((pixel >> 8) & 0xff); + color+=(pixel & 0xff); + colorset<<=1; + if (color>=3*128) + colorset|=1; + } + bos.write((byte)colorset); + } + if (rest>0) { + colorset=0; + for (int sh=0; sh> 16) & 0xff); + color+=((pixel >> 8) & 0xff); + color+=(pixel & 0xff); + colorset<<=1; + if (color>=3*128) + colorset|=1; + } + colorset<<=8-rest; + bos.write((byte)colorset); + } + } + break; + case GREYSCALE_MODE: + for (int y=0;y> 16) & 0xff); + color+=((pixel >> 8) & 0xff); + color+=(pixel & 0xff); + bos.write((byte)(color/3)); + } + } + break; + case COLOR_MODE: + for (int y=0;y> 16) & 0xff)); + bos.write((byte)((pixel >> 8) & 0xff)); + bos.write((byte)(pixel & 0xff)); + } + } + break; + } + bos.close(); + write(compressed.size()); + crc.reset(); + write("IDAT".getBytes()); + write(compressed.toByteArray()); + write((int) crc.getValue()); + write(0); + crc.reset(); + write("IEND".getBytes()); + write((int) crc.getValue()); + out.close(); + } + + /** Static method performing screen capture into PNG image format file with given fileName. + * @param rect Rectangle of screen to be captured + * @param fileName file name for screen capture PNG image file + * @throws IOException + * @throws AWTException */ + public static void captureScreen(Rectangle rect, String fileName) throws AWTException, IOException { + captureScreen(rect, fileName, GREYSCALE_MODE); + } + + /** Static method performing screen capture into PNG image format file with given fileName. + * @param rect Rectangle of screen to be captured + * @param mode image color mode + * @param fileName file name for screen capture PNG image file + * @throws AWTException + * @throws IOException */ + public static void captureScreen(Rectangle rect, String fileName, byte mode) throws AWTException, IOException { + BufferedImage capture=new Robot().createScreenCapture(rect); + BufferedOutputStream file=new BufferedOutputStream(new FileOutputStream(fileName)); + PNGEncoder encoder=new PNGEncoder(file, mode); + encoder.encode(capture); + } + + /** Static method performing one component screen capture into PNG image format file with given fileName. + * @param comp Component to be captured + * @param fileName String image target filename + * @throws IOException + * @throws AWTException */ + public static void captureScreen(Component comp, String fileName) throws AWTException, IOException { + captureScreen(comp, fileName, GREYSCALE_MODE); + } + + /** Static method performing one component screen capture into PNG image format file with given fileName. + * @param comp Component to be captured + * @param fileName String image target filename + * @param mode image color mode + * @throws IOException + * @throws AWTException */ + public static void captureScreen(Component comp, String fileName, byte mode) throws AWTException, IOException { +captureScreen(new Rectangle(comp.getLocationOnScreen(), + comp.getSize()), + fileName, mode); + } + + + /** Static method performing whole screen capture into PNG image format file with given fileName. + * @param fileName String image target filename + * @throws IOException + * @throws AWTException + * @throws HeadlessException */ + public static void captureScreen(String fileName) throws HeadlessException, AWTException, IOException { + captureScreen(fileName, GREYSCALE_MODE); + } + + /** Static method performing whole screen capture into PNG image format file with given fileName. + * @param fileName String image target filename + * @param mode image color mode + * @throws IOException + * @throws AWTException + * @throws HeadlessException */ + public static void captureScreen(String fileName, byte mode) throws HeadlessException, AWTException, IOException { +captureScreen(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()), fileName, mode); + } +} \ No newline at end of file diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/lists/AbstractList.java b/src/main/java/com/github/oxygenPlugins/common/gui/lists/AbstractList.java new file mode 100644 index 0000000..cb07fcc --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/lists/AbstractList.java @@ -0,0 +1,536 @@ +package com.github.oxygenPlugins.common.gui.lists; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; + +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.JToolBar; +import javax.swing.ScrollPaneLayout; +import javax.swing.border.Border; + +import com.github.oxygenPlugins.common.gui.lists.items.AbstractListItem; +import com.github.oxygenPlugins.common.gui.lists.items.ItemGroup; +import com.github.oxygenPlugins.common.gui.lists.items._ListGroupNode; +import com.github.oxygenPlugins.common.gui.lists.items._ListNode; +import com.github.oxygenPlugins.common.gui.swing.SwingUtil; + +public abstract class AbstractList & Comparable> + extends JPanel implements KeyListener, MouseListener { + + private Border border; + private final GridBagLayout gbl_content = new GridBagLayout(); + protected final JPanel content = new JPanel(gbl_content); + protected JPanel endPanel = new JPanel(); + protected JPanel emptyEndPanel = new JPanel(); + private final JPanel toolbarPanel = new JPanel(); + private final JPanel bottombarPanel = new JPanel(); + private final GridBagLayout gbl_toolbarPanel = new GridBagLayout(); + private final GridBagLayout gbl_bottombarPanel = new GridBagLayout(); + protected boolean isMultiSelectable = true; + + private ArrayList itemList = new ArrayList(); + private ArrayList> groups = new ArrayList>(); + + private int messageIndex = 0; + + @SuppressWarnings("rawtypes") + private HashMap itemByPosition = new HashMap(); + private ArrayList selectedItem = new ArrayList(); + private JScrollPane scrollPane; + private final Theme theme; + + public AbstractList(Theme theme) { + this.theme = theme; + GridBagLayout gbl = new GridBagLayout(); + this.setLayout(gbl); + + toolbarPanel.setLayout(gbl_toolbarPanel); + bottombarPanel.setLayout(gbl_bottombarPanel); + + scrollPane = new JScrollPane(this.content); + ScrollPaneLayout spl = new ScrollPaneLayout(); + scrollPane.setLayout(spl); + + scrollPane.setBackground(theme.getDefaultBackgroundColor()); + scrollPane.setOpaque(true); + + JScrollBar vertScrollBar = new JScrollBar(); + vertScrollBar.setUnitIncrement(100); + JScrollBar horScrollBar = new JScrollBar(JScrollBar.HORIZONTAL); + horScrollBar.setUnitIncrement(100); + + scrollPane.setVerticalScrollBar(vertScrollBar); + scrollPane.setHorizontalScrollBar(horScrollBar); + + endPanel.setBackground(theme.getDefaultBackgroundColor()); + emptyEndPanel.setBackground(theme.getDefaultBackgroundColor()); + + SwingUtil.addComponent(this, gbl, toolbarPanel, 0, 0, 1, 1, 1.0, 0.0, + GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH); + SwingUtil.addComponent(this, gbl, scrollPane, 0, 1, 1, 1, 0.0, 1.0, + GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH); + SwingUtil.addComponent(this, gbl, bottombarPanel, 0, 2, 1, 1, 1.0, 0.0, + GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH); + border = BorderFactory.createEmptyBorder(); + this.setBorder(border); + + // border = BorderFactory.createLineBorder(new Color(0, 100, 100, 70)); + this.content.setBackground(theme.getDefaultBackgroundColor()); + + this.endPanel.addMouseListener(this); + + this.content.addMouseListener(this); + this.content.addKeyListener(this); + + } + + public AbstractList() { + this(new DefaultTheme()); + } + public AbstractList(String title) { + this(title, new DefaultTheme()); + } + + public AbstractList(String title, Theme theme) { + this(theme); + if(title != null){ + border = BorderFactory + .createTitledBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, + Color.BLACK), title); + this.setBorder(border); + } + } + +// protected void setTheme(Theme theme){ +// +// setBgColor(theme.getDefaultBackgroundColor()); +// } +// +// private void setBgColor(Color bgc){ +// this.scrollPane.setBackground(bgc); +// this.endPanel.setBackground(bgc); +// this.content.setBackground(bgc); +// this.emptyEndPanel.setBackground(bgc); +// this.setBackground(bgc); +// this.updateUI(); +// } + + protected void addComponentToToolbar(JComponent comp, int x, int y, + int width, int height, double weightx, double weighty, int anchor, + int fill){ + addComponentToToolbar(comp, x, y, width, height, weightx, weighty, anchor, fill, new Insets(0, 0, 0, 0)); + } + protected void addComponentToToolbar(JComponent comp, int x, int y, + int width, int height, double weightx, double weighty, int anchor, + int fill, Insets insets) { + SwingUtil.addComponent(this.toolbarPanel, gbl_toolbarPanel, comp, x, y, + width, height, weightx, weighty, anchor, fill, insets); + } + protected void addComponentToBottombar(JComponent comp, int x, int y, + int width, int height, double weightx, double weighty, int anchor, + int fill) { + addComponentToBottombar(comp, x, y, width, height, weightx, weighty, anchor, fill, new Insets(0, 0, 0, 0)); + } + protected void addComponentToBottombar(JComponent comp, int x, int y, + int width, int height, double weightx, double weighty, int anchor, + int fill, Insets insets) { + SwingUtil.addComponent(this.bottombarPanel, gbl_bottombarPanel, comp, x, y, + width, height, weightx, weighty, anchor, fill, insets); + } + + public void addToolbar(JToolBar toolbar) { + this.toolbarPanel.add(toolbar); + } + + private Insets itemInsets = new Insets(0, 1, 0, 1); + + public void addListItem(ListItemType item) { + if (!this.content.isEnabled()) + this.content.setEnabled(true); + +// item.setTheme(this.theme); + this.itemList.add(item); + + this.content.remove(this.endPanel); + this.content.remove(emptyEndPanel); + + SwingUtil.addComponent(this.content, gbl_content, item, 0, + messageIndex++, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH, + GridBagConstraints.BOTH, itemInsets); + SwingUtil.addComponent(this.content, gbl_content, this.endPanel, 0, + messageIndex + 1, 1, 1, 1.0, 1.0, GridBagConstraints.NORTH, + GridBagConstraints.BOTH, itemInsets); + + this.itemByPosition.put(item, messageIndex); + } + + public void addListItem(ListItemType[] items) { + Arrays.sort(items); + for (ListItemType item : items) { + addListItem(item); + } + + } + + public void addListItem(ArrayList items) { + Collections.sort(items); + for (ListItemType item : items) { + addListItem(item); + } + } + + protected ArrayList getListItems(){ + return new ArrayList(this.itemList); + } + + public ItemGroup createItemGroup(ArrayList items, ArrayList> subGroups, _ListGroupNode node){ + Collections.sort(items); + ItemGroup group = new ItemGroup( + node, items, subGroups, 0, this, null, this.theme, false) { + private static final long serialVersionUID = -420997520077674539L; + + @Override + public void expand() { + for (ListItemType item : this.items) { + showItem(item); + } + super.expand(); + } + + @Override + public void collapse() { + for (ListItemType item : this.items) { + hideItem(item); + } + super.collapse(); + } + + }; + + return group; + + } + + protected ItemGroup addListItemAsGroup(ArrayList items, + _ListGroupNode node) { + return addListItemAsGroup(items, new ArrayList>(), node); + } + + protected ItemGroup addListItemAsGroup(ArrayList items, ArrayList> subGroups, + _ListGroupNode node) { + ItemGroup group = createItemGroup(items, subGroups, node); + this.addListItem(group); + return group; + } + + @SuppressWarnings("rawtypes") + private void showItem(AbstractListItem item) { + item.setVisible(true); + } + + @SuppressWarnings("rawtypes") + private void hideItem(AbstractListItem item) { + item.setVisible(false); + } + + public void addListItem(ItemGroup group) { + if (!this.content.isEnabled()) + this.content.setEnabled(true); + synchronized (group) { + + this.content.remove(this.endPanel); + this.content.remove(this.emptyEndPanel); + SwingUtil.addComponent(this.content, gbl_content, group, 0, + messageIndex++, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH, + GridBagConstraints.BOTH, itemInsets); + SwingUtil.addComponent(this.content, gbl_content, this.endPanel, 0, + messageIndex + 1, 1, 1, 1.0, 1.0, GridBagConstraints.NORTH, + GridBagConstraints.BOTH, itemInsets); + + this.itemByPosition.put(group, messageIndex); + + this.groups.add(group); + + for (ItemGroup subGroup : group.getSubGroups()) { + this.addListItem(subGroup); + } + + } + + this.addListItem(group.getItems()); + + } + + public void removeAllItems() { + this.content.removeAll(); + this.messageIndex = 0; + this.itemList = new ArrayList(); + this.content.setEnabled(false); + SwingUtil.addComponent(this.content, gbl_content, this.emptyEndPanel, 0, + messageIndex + 1, 1, 1, 1.0, 1.0, GridBagConstraints.NORTH, + GridBagConstraints.BOTH, itemInsets); + } + + public boolean isSelectedItem(ListItemType item) { + return getSelectedItem().contains(item); + } + + public ArrayList getSelectedItem() { + return this.selectedItem; + } + + public void unselectItems() { + if (this.selectedItem != null) { + for (ListItemType item : this.selectedItem) { + item.setSelection(false); + } + this.selectedItem = new ArrayList(); + } + + } + + private void unselectItem(ListItemType item) { + selectedItem.remove(item); + item.setSelection(false); + } + public void selectUnselectItem(ArrayList items) { + unselectItems(); + for (ListItemType item : items) { + select(item); + } + } + + + public void selectUnselectItem(InputEvent e, ArrayList items) { + if(this.isMultiSelectable){ + if (!e.isControlDown()) { + unselectItems(); + } + for (ListItemType item : items) { + select(item); + } + } + } + + private ListItemType getSelectAnchor(ListItemType item){ + return this.selectedItem.get(0); + } + + public void selectUnselectItem(ListItemType item) { + unselectItems(); + select(item); + } + public void selectUnselectItem(InputEvent e, ListItemType item) { + if (e.isShiftDown() && this.isMultiSelectable) { + shiftSelectUnselect(item); + } else if (e.isControlDown() && this.isMultiSelectable) { + ctrlSelectUnselect(item); + } else { + selectUnselectItem(item); + } + } + + private void shiftSelectUnselect(ListItemType item) { + ListItemType lastSelectedItem = selectedItem.size() > 0 ? getSelectAnchor(item) : item; + unselectItems(); + if (lastSelectedItem != null) { + select(lastSelectedItem, item); + } else { + select(item); + } + } + + private void ctrlSelectUnselect(ListItemType item) { + if (item.isSelected()) { + unselectItem(item); + } else { + select(item); + } + } + + private void select(ListItemType item) { + this.selectedItem.add(item); + item.setSelection(true); + } + + private void select(ListItemType from, ListItemType to) { + boolean selecting = false; + if(this.isMultiSelectable && from != to){ + boolean reverse = this.itemList.indexOf(from) > this.itemList.indexOf(to); + + ArrayList reverseList = new ArrayList(this.itemList); + + if(reverse){ + Collections.reverse(reverseList); + } + + for (ListItemType item : reverseList) { + if (item == from || item == to) { + selecting = !selecting; + select(item); + } else if (selecting) { + select(item); + } + } + } else { + select(from); + } + } + + public ListItemType getListItemByNode(_ListNode node) { + for (ListItemType item : this.itemList) { + if (item.getModelNode() == node) + return item; + } + return null; + } + + public ListItemType getNextItem(ListItemType item){ + int pos = this.itemByPosition.get(item); + return getAllItems().get(pos + 1); + } + + public ListItemType getBeforeItem(ListItemType item){ + int pos = this.itemByPosition.get(item); + if(pos > 0) + return getAllItems().get(pos - 1); + return null; + } + + public ArrayList getAllItems() { + return this.itemList; + } + + private static final long serialVersionUID = 2271347445049935275L; + + // + // Key Listener + // + + public void implementShortCut(Container comp) { + comp.removeKeyListener(this); + comp.addKeyListener(this); +// for (Component childComp : comp.getComponents()) { +// this.implementShortCut(childComp); +// } + } + + public void implementShortCut(Component comp) { + if (comp instanceof Container) { + this.implementShortCut((Container) comp); + } else { + comp.removeKeyListener(this); + comp.addKeyListener(this); + } + } + + @Override + public Component add(Component comp) { +// comp.removeKeyListener(this); +// comp.addKeyListener(this); + return super.add(comp); + } + + @Override + public void keyTyped(KeyEvent ke) { + + } + + @Override + public void keyReleased(KeyEvent ke) { +// if (KeyEvent.VK_CONTROL == ke.getExtendedKeyCode()) { +// ctrlKeyPressed = false; +// } else if (KeyEvent.VK_SHIFT == ke.getExtendedKeyCode()) { +// shiftKeyPressed = false; +// } + } + + @Override + public void keyPressed(KeyEvent ke) { +// if (KeyEvent.VK_CONTROL == ke.getExtendedKeyCode()) { +// ctrlKeyPressed = true; +// } else if (KeyEvent.VK_SHIFT == ke.getExtendedKeyCode()) { +// shiftKeyPressed = true; +// } + } + + protected void showHideItems(ArrayList showItems, + ArrayList hideItems, boolean hideGroups) { + + HashSet collapsedItems = new HashSet(); + + for (ItemGroup group : this.groups) { + if(!group.isExpanded()){ + collapsedItems.addAll(group.getItems()); + } + } + + for (ListItemType showItem : showItems) { + if(!collapsedItems.contains(showItem)) + showItem(showItem); + } + + for (ListItemType hideItem : hideItems) { + hideItem(hideItem); + } + + if(hideGroups){ + for (ItemGroup item : this.groups) { + item.checkVisibility(); + } + } + } + + @Override + public void mouseReleased(MouseEvent arg0) {} + + @Override + public void mousePressed(MouseEvent arg0) {} + + @Override + public void mouseExited(MouseEvent arg0) {} + + @Override + public void mouseEntered(MouseEvent arg0) {} + + @Override + public void mouseClicked(MouseEvent me) { + if(content.contains(me.getX(), me.getY())){ + content.requestFocus(); + } + } + + public Theme getTheme() { + return this.theme; + } + +// public JPanel getEmptyPanel(){ +// return new JPanel(); +// } + + // public boolean isCtrlPressed(){ + // return ctrlKeyPressed; + // } + // + // public boolean isShiftPressed(){ + // return shiftKeyPressed; + // } +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/lists/DarkTheme.java b/src/main/java/com/github/oxygenPlugins/common/gui/lists/DarkTheme.java new file mode 100644 index 0000000..41f7229 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/lists/DarkTheme.java @@ -0,0 +1,123 @@ +package com.github.oxygenPlugins.common.gui.lists; + +import java.awt.Color; + +import javax.swing.BorderFactory; +import javax.swing.border.Border; + +public class DarkTheme implements Theme { + + private static final Color DEFAULT_BG_COLOR = new Color(80, 80, 80); + private static final Color[] DEFAULT_FG_COLOR = new Color[]{new Color(200, 200, 200), Color.GRAY, Color.BLUE, new Color(155, 155, 0, 255), new Color(0, 155, 155, 255)}; + private static final Border DEFAULT_BORDER = BorderFactory.createEmptyBorder(1, 0, 1, 0); + + private static final Color HOVER_BG_COLOR = new Color(80, 80, 80); + private static final Color[] HOVER_FG_COLOR = new Color[]{new Color(200, 200, 200), Color.GRAY, Color.BLUE, new Color(155, 155, 0, 255), new Color(0, 155, 155, 255)}; + private static final Border HOVER_BORDER = BorderFactory.createMatteBorder(1, 0, 1, 0, new Color(0, 150, 255)); + + private static final Color SELECTION_BG_COLOR = new Color(55, 55, 55); + private static final Color[] SELECTION_FG_COLOR = new Color[]{new Color(200, 200, 200), Color.GRAY, Color.BLUE, new Color(155, 155, 0, 255), new Color(0, 155, 155, 255)}; + private static final Border SELECTION_BORDER = BorderFactory.createMatteBorder(1, 0, 1, 0, new Color(200, 200, 200)); + + private static final Color FOCUS_BG_COLOR = Color.WHITE; + private static final Color[] FOCUS_FG_COLOR = new Color[]{Color.BLACK, Color.GRAY, Color.BLUE, new Color(155, 155, 0, 255), new Color(0, 155, 155, 255)}; + private static final Border FOCUS_BORDER = BorderFactory.createMatteBorder(1, 0, 1, 0, new Color(0, 0, 0)); + + @Override + public Color getDefaultBackgroundColor() { + // TODO Auto-generated method stub + return DEFAULT_BG_COLOR; + } + + @Override + public Color getDefaultForegroundColor() { + // TODO Auto-generated method stub + return getDefaultForegroundColor(COLOR_TYPE_STANDARD); + } + + @Override + public Border getDefaultBorder() { + // TODO Auto-generated method stub + return DEFAULT_BORDER; + } + + @Override + public Color getHoverBackgroundColor() { + // TODO Auto-generated method stub + return HOVER_BG_COLOR; + } + + @Override + public Color getHoverForegroundColor() { + // TODO Auto-generated method stub + return getHoverForegroundColor(COLOR_TYPE_STANDARD); + } + + @Override + public Border getHoverBorder() { + // TODO Auto-generated method stub + return HOVER_BORDER; + } + + @Override + public Color getSelectionBackgroundColor() { + // TODO Auto-generated method stub + return SELECTION_BG_COLOR; + } + + @Override + public Color getSelectionForegroundColor() { + // TODO Auto-generated method stub + return getSelectionForegroundColor(COLOR_TYPE_STANDARD); + } + + @Override + public Border getSelectionBorder() { + // TODO Auto-generated method stub + return SELECTION_BORDER; + } + + @Override + public Color getDefaultForegroundColor(int type) { + // TODO Auto-generated method stub + return DEFAULT_FG_COLOR[type]; + } + + @Override + public Color getHoverForegroundColor(int type) { + // TODO Auto-generated method stub + return HOVER_FG_COLOR[type]; + } + + @Override + public Color getSelectionForegroundColor(int type) { + // TODO Auto-generated method stub + return SELECTION_FG_COLOR[type]; + } + + @Override + public boolean isDark() { + return true; + } + + @Override + public Color getFocusForegroundColor(int type) { + return FOCUS_FG_COLOR[type]; + } + + @Override + public Border getFocusBorder() { + return FOCUS_BORDER; + } + + @Override + public Color getFocusForegroundColor() { + return getFocusForegroundColor(COLOR_TYPE_STANDARD); + } + + @Override + public Color getFocusBackgroundColor() { + return FOCUS_BG_COLOR; + } + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/lists/DefaultTheme.java b/src/main/java/com/github/oxygenPlugins/common/gui/lists/DefaultTheme.java new file mode 100644 index 0000000..6cc74d4 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/lists/DefaultTheme.java @@ -0,0 +1,161 @@ +package com.github.oxygenPlugins.common.gui.lists; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.PaintContext; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.image.ColorModel; + +import javax.swing.BorderFactory; +import javax.swing.border.AbstractBorder; +import javax.swing.border.Border; + +public class DefaultTheme implements Theme { + + private static final Color DEFAULT_BG_COLOR = Color.WHITE; + private static final Color[] DEFAULT_FG_COLOR = new Color[]{Color.BLACK, Color.GRAY, Color.BLUE, new Color(155, 155, 0, 255), new Color(0, 155, 155, 255)}; + private static final Border DEFAULT_BORDER = BorderFactory.createEmptyBorder(1, 0, 1, 0); + + private static final Color HOVER_BG_COLOR = Color.WHITE; + private static final Color[] HOVER_FG_COLOR = new Color[]{Color.BLACK, Color.GRAY, Color.BLUE, new Color(155, 155, 0, 255), new Color(0, 155, 155, 255)}; + private static final Border HOVER_BORDER = BorderFactory.createMatteBorder(1, 0, 1, 0, new Color(0, 150, 255)); + + private static final Color SELECTION_BG_COLOR = new Color(0, 255, 255); + private static final Color[] SELECTION_FG_COLOR = new Color[]{Color.BLACK, Color.GRAY, Color.BLUE, new Color(155, 155, 0, 255), new Color(0, 155, 155, 255)}; + private static final Border SELECTION_BORDER = BorderFactory.createMatteBorder(1, 0, 1, 0, new Color(0, 150, 255)); + + private static final Color FOCUS_BG_COLOR = Color.WHITE; + private static final Color[] FOCUS_FG_COLOR = new Color[]{Color.BLACK, Color.GRAY, Color.BLUE, new Color(155, 155, 0, 255), new Color(0, 155, 155, 255)}; +// private static final Border FOCUS_BORDER = BorderFactory.createMatteBorder(1, 0, 1, 0, new Color(0, 0, 0)); + private static final Border FOCUS_BORDER = BorderFactory.createDashedBorder(new Color(0, 150, 255)); + + + // type 1: Color.BLACK + // type 2: Color.GRAY + // type 3: Color.BLUE + // http: new Color(155, 155, 0, 255) + // arch: new Color(0, 155, 155, 255) +// +// DEFAULT +// + @Override + public Color getDefaultBackgroundColor() { + // TODO Auto-generated method stub + return DEFAULT_BG_COLOR; + } + + @Override + public Color getDefaultForegroundColor() { + // TODO Auto-generated method stub + return getDefaultForegroundColor(COLOR_TYPE_STANDARD); + } + + @Override + public Border getDefaultBorder() { + // TODO Auto-generated method stub + return DEFAULT_BORDER; + } + + @Override + public Color getDefaultForegroundColor(int type) { + // TODO Auto-generated method stub + return DEFAULT_FG_COLOR[type]; + } + +// +// HOVER +// + + @Override + public Color getHoverBackgroundColor() { + // TODO Auto-generated method stub + return HOVER_BG_COLOR; + } + + @Override + public Color getHoverForegroundColor() { + // TODO Auto-generated method stub + return getHoverForegroundColor(COLOR_TYPE_STANDARD); + } + + @Override + public Border getHoverBorder() { + // TODO Auto-generated method stub + return HOVER_BORDER; + } + + @Override + public Color getHoverForegroundColor(int type) { + // TODO Auto-generated method stub + return HOVER_FG_COLOR[type]; + } + +// +// SELECTION +// + @Override + public Color getSelectionBackgroundColor() { + // TODO Auto-generated method stub + return SELECTION_BG_COLOR; + } + + @Override + public Color getSelectionForegroundColor() { + // TODO Auto-generated method stub + return getSelectionForegroundColor(COLOR_TYPE_STANDARD); + } + + @Override + public Border getSelectionBorder() { + // TODO Auto-generated method stub + return SELECTION_BORDER; + } + + @Override + public Color getSelectionForegroundColor(int type) { + // TODO Auto-generated method stub + return SELECTION_FG_COLOR[type]; + } + + +// +// FOCUS +// + + @Override + public Color getFocusForegroundColor() { + // TODO Auto-generated method stub + return getDefaultForegroundColor(COLOR_TYPE_STANDARD); + } + + @Override + public Color getFocusForegroundColor(int type){ + return FOCUS_FG_COLOR[type]; + } + + @Override + public Border getFocusBorder() { + // TODO Auto-generated method stub + return FOCUS_BORDER; + } + + @Override + public Color getFocusBackgroundColor() { + // TODO Auto-generated method stub + return FOCUS_BG_COLOR; + } + + + @Override + public boolean isDark() { + return false; + } + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/lists/Theme.java b/src/main/java/com/github/oxygenPlugins/common/gui/lists/Theme.java new file mode 100644 index 0000000..b66801a --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/lists/Theme.java @@ -0,0 +1,36 @@ +package com.github.oxygenPlugins.common.gui.lists; + +import java.awt.Color; + +import javax.swing.border.Border; + +public interface Theme { + + + public static final int COLOR_TYPE_STANDARD = 0; + public static final int COLOR_TYPE_INACTIVE = 1; + public static final int COLOR_TYPE_HIGHLIGHT = 2; + public static final int COLOR_TYPE_HTTP = 3; + public static final int COLOR_TYPE_ARCH = 4; + + Color getDefaultBackgroundColor(); + Color getDefaultForegroundColor(); + Color getDefaultForegroundColor(int type); + Border getDefaultBorder(); + + Color getHoverBackgroundColor(); + Color getHoverForegroundColor(); + Color getHoverForegroundColor(int type); + Border getHoverBorder(); + + Color getSelectionBackgroundColor(); + Color getSelectionForegroundColor(); + Color getSelectionForegroundColor(int type); + Border getSelectionBorder(); + + boolean isDark(); + Color getFocusForegroundColor(int type); + Border getFocusBorder(); + Color getFocusForegroundColor(); + Color getFocusBackgroundColor(); +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/lists/items/AbstractItemMouseListener.java b/src/main/java/com/github/oxygenPlugins/common/gui/lists/items/AbstractItemMouseListener.java new file mode 100644 index 0000000..3461c70 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/lists/items/AbstractItemMouseListener.java @@ -0,0 +1,56 @@ +package com.github.oxygenPlugins.common.gui.lists.items; + +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import com.github.oxygenPlugins.common.gui.lists.AbstractList; + + +public abstract class AbstractItemMouseListener & Comparable> + extends MouseAdapter { + + protected final ListItemType item; + protected final AbstractList list; + @SuppressWarnings("unused") + private boolean wasDoubleClick; +// private Timer timer; + + public AbstractItemMouseListener(ListItemType item, + AbstractList list) { + this.item = item; + this.list = list; + } + + public void mouseClicked(final MouseEvent e) { + if(e.isPopupTrigger()) { + return; + } else if (e.getClickCount() == 2) { + doubleClick(e); + wasDoubleClick = true; + } else { + + list.selectUnselectItem(e, item); + oneClick(e, item.isSelected()); + +// if (wasDoubleClick) { +// wasDoubleClick = false; // reset flag +// } else { +// } + + // Integer timerinterval = (Integer) + // Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval"); + // timer = new Timer(timerinterval.intValue(), new ActionListener() + // { + // public void actionPerformed(ActionEvent evt) { + // + // } + // }); + // timer.setRepeats(false); + // timer.start(); + } + } + + public abstract void oneClick(MouseEvent e, boolean isSelected); + + public abstract void doubleClick(MouseEvent e); +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/lists/items/AbstractListItem.java b/src/main/java/com/github/oxygenPlugins/common/gui/lists/items/AbstractListItem.java new file mode 100644 index 0000000..c00ede1 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/lists/items/AbstractListItem.java @@ -0,0 +1,335 @@ +package com.github.oxygenPlugins.common.gui.lists.items; + +import java.awt.Color; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Point; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.io.IOException; +import java.util.HashMap; + +import javax.swing.Icon; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.border.Border; + +import com.github.oxygenPlugins.common.gui.lists.DefaultTheme; +import com.github.oxygenPlugins.common.gui.lists.Theme; +import com.github.oxygenPlugins.common.gui.swing.SwingUtil; + + + +public abstract class AbstractListItem extends + JPanel { + + // private static final Color HOVER_COLOR = Color.WHITE; + // // private static final Color DEFAULT_COLOR = Color.WHITE; + // private static final Color DEFAULT_COLOR = new Color(50, 50, 50); + // private static final Color DEFAULT_FONT_COLOR = Color.BLACK; + // private static final Color HOVER_FONT_COLOR = Color.BLACK; + // private static final Color SELECTION_COLOR = new Color(0, 255, 255); + // private static final Color SELECTION_FONT_COLOR = Color.BLACK; + // private static final Border DEFAULT_BORDER = + // BorderFactory.createEmptyBorder(1, 0, 1, 0); + // private static final Border HOVER_SELECT_BORDER = + // BorderFactory.createMatteBorder(1, 0, 1, 0, new Color(0, 150, 255)); + + private static final long serialVersionUID = 159899019060744554L; + + private GridBagLayout gbl = new GridBagLayout(); + + private Theme theme = new DefaultTheme(); + + private Color usedBgColor = theme.getDefaultBackgroundColor(); + private Color usedFontColor = theme.getDefaultForegroundColor(); + + private Color defaultFontColor = this.theme.getDefaultForegroundColor(); + private Color selectFontColor = this.theme.getSelectionForegroundColor(); + private Color howerFontColor = theme.getHoverForegroundColor(); + + private JLabel titleLabel; + private boolean isSelected; + protected final ModelNodeType node; + protected final ControlPanel controlPanel = new ControlPanel(new Mouse()); + private final JLabel iconLabel; + private MouseListener selcetionListener; + private int paddingLabel; + // private JPopupMenu menu = null; + private HashMap menuByModifier = new HashMap(); + + private Border usedBorder; + + public AbstractListItem(ModelNodeType node, Icon defaultIcon) { + this(node, 0, defaultIcon, new DefaultTheme()); + } + public AbstractListItem(ModelNodeType node, int level, Icon defaultIcon) { + this(node, level, defaultIcon, new DefaultTheme()); + } + + public AbstractListItem(ModelNodeType node, Icon defaultIcon, Theme theme) { + this(node, 0, defaultIcon, theme); + } + + public AbstractListItem(ModelNodeType node, int level, Icon defaultIcon, + Theme theme) { + this.node = node; + this.theme = theme; + this.setLayout(gbl); + titleLabel = new JLabel(node.toString()); + + Icon icon = null; + if (node.hasIcon()) { + try { + icon = node.getIcon(); + } catch (IOException e) { + icon = defaultIcon; + } + } else { + icon = defaultIcon; + } + iconLabel = new JLabel(icon); + + int iconW = icon != null ? icon.getIconWidth() : 0; + paddingLabel = 2; + if (iconW > 16) { + paddingLabel += iconW - 16; + } + + SwingUtil.addComponent(this, gbl, iconLabel, 0, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, + level * 10, 0, paddingLabel)); + SwingUtil.addComponent(this, gbl, titleLabel, 1, 0, 1, 1, 1.0, 0.0, + GridBagConstraints.WEST, GridBagConstraints.BOTH); + SwingUtil.addComponent(this, gbl, this.controlPanel, 2, 0, 1, 1, 0.0, + 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, + new Insets(0, 0, 0, 5)); + + titleLabel.setForeground(theme + .getDefaultForegroundColor(Theme.COLOR_TYPE_STANDARD)); + + this.setBackground(theme.getDefaultBackgroundColor()); + this.setForeground(theme.getDefaultForegroundColor()); + this.setBorder(theme.getDefaultBorder()); + // setTheme(new DefaultTheme()); + + usedBgColor = this.theme.getDefaultBackgroundColor(); + usedFontColor = this.theme.getDefaultForegroundColor(); + usedBorder = this.theme.getDefaultBorder(); + + defaultFontColor = this.theme.getDefaultForegroundColor(); + selectFontColor = this.theme.getSelectionForegroundColor(); + howerFontColor = this.theme.getHoverForegroundColor(); + + this.addMouseListener(new Mouse()); + this.setFocusable(true); + this.addFocusListener(new FocusListener() { + + @Override + public void focusLost(FocusEvent e) { + setBorder(usedBorder); + } + + @Override + public void focusGained(FocusEvent e) { + usedBorder = getBorder(); + setBorder(AbstractListItem.this.theme.getFocusBorder()); + } + }); + } + + // public void setTheme(Theme theme){ + // this.theme = theme; + // + + // this.repaint(); + // } + + public void addSelectionListener(MouseListener ml) { + // this.addMouseListener(ml); + this.selcetionListener = ml; + } + + public void setLevel(int level) { + GridBagConstraints gbc = gbl.getConstraints(iconLabel); + gbc.insets = new Insets(0, level * 10, 0, paddingLabel); + gbl.setConstraints(iconLabel, gbc); + this.repaint(); + } + + protected void addIconMouseAdapter(MouseAdapter mouse) { + this.iconLabel.addMouseListener(mouse); + this.iconLabel.addMouseMotionListener(mouse); + this.iconLabel.addMouseWheelListener(mouse); + } + + public void implementPopupMenu(JPopupMenu menu, int modifier) { + this.menuByModifier.put(modifier, menu); + } + + public void implementPopupMenu(JPopupMenu[] menus) { + this.implementPopupMenu(menus, new int[] { NO_MODIFIER, SHIFT_DOWN, + CTRL_DOWN }); + } + + public void implementPopupMenu(JPopupMenu[] menus, int[] modifiers) { + int i = 0; + for (int mod : modifiers) { + if (i < menus.length) { + this.menuByModifier.put(mod, menus[i]); + } + i++; + } + } + + public final static int NO_MODIFIER = 0; + + public final static int ALT_DOWN = MouseEvent.ALT_DOWN_MASK; + public final static int CTRL_DOWN = MouseEvent.CTRL_DOWN_MASK; + public final static int SHIFT_DOWN = MouseEvent.SHIFT_DOWN_MASK; + + public void implementPopupMenu(JPopupMenu menu) { + this.implementPopupMenu(menu, NO_MODIFIER); + } + + public class Mouse extends MouseAdapter { + private Border usedBorder = theme.getDefaultBorder(); + + @Override + public void mousePressed(MouseEvent e) { + super.mousePressed(e); + if (e.isPopupTrigger()) { + doPop(e); + } + } + + @Override + public void mouseReleased(MouseEvent e) { + super.mouseReleased(e); + if (e.isPopupTrigger()) { + doPop(e); + } + } + + @Override + public void mouseEntered(MouseEvent e) { + usedBorder = getBorder(); + if (isSelected) { + setBorder(theme.getSelectionBorder()); + } else { + setBackground(theme.getHoverBackgroundColor()); + titleLabel.setForeground(howerFontColor); + } + updateUI(); + super.mouseEntered(e); + } + + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + if (selcetionListener != null && !e.isPopupTrigger()) { + selcetionListener.mouseClicked(e); + } + // if(AbstractListItem.this.contains(e.getX(), e.getY())){ + // AbstractListItem.this.requestFocus(); + // } + } + + private void doPop(MouseEvent e) { + if ((!isSelected) && selcetionListener != null) { + selcetionListener.mouseClicked(e); + } + int modifier = NO_MODIFIER; + if (e.isShiftDown()) { + modifier = SHIFT_DOWN; + } else if (e.isControlDown()) { + modifier = CTRL_DOWN; + } + + if (!menuByModifier.containsKey(modifier)) { + modifier = NO_MODIFIER; + } + + JPopupMenu menu = null; + if (menuByModifier.containsKey(modifier)) { + menu = menuByModifier.get(modifier); + menu.show(e.getComponent(), e.getX(), e.getY()); + } + } + + @Override + public void mouseExited(MouseEvent e) { + setBorder(usedBorder); + setBackground(usedBgColor); + titleLabel.setForeground(usedFontColor); + updateUI(); + super.mouseExited(e); + } + } + + // public abstract Icon getDefaultIcon(); + + public void setSelection(boolean isSelected) { + this.isSelected = isSelected; + if (isSelected) { + this.setBackground(theme.getSelectionBackgroundColor()); + titleLabel.setForeground(this.selectFontColor); + this.usedBgColor = theme.getSelectionBackgroundColor(); + this.usedFontColor = this.selectFontColor; + } else { + this.setBackground(theme.getDefaultBackgroundColor()); + titleLabel.setForeground(this.defaultFontColor); + this.usedBgColor = theme.getDefaultBackgroundColor(); + this.usedFontColor = this.defaultFontColor; + } + repaint(); + } + + protected void updateText() { + titleLabel.setText(node.toString()); + this.repaint(); + } + + protected void setLabelStyle(int style) { + Font f = titleLabel.getFont(); + f = new Font(f.getName(), style, f.getSize()); + titleLabel.setFont(f); + titleLabel.repaint(); + } + + protected void setLabelColorType(int type) { + titleLabel.setForeground(theme.getDefaultForegroundColor(type)); + this.usedFontColor = theme.getDefaultForegroundColor(type); + this.defaultFontColor = theme.getDefaultForegroundColor(type); + this.selectFontColor = theme.getSelectionForegroundColor(type); + this.howerFontColor = theme.getHoverForegroundColor(type); + } + + public boolean isSelected() { + return this.isSelected; + } + + public ModelNodeType getModelNode() { + return this.node; + } + + @Override + public String toString() { + return node.toString(); + } + + public boolean isOnControllIcon(Point point) { + return this.controlPanel.contains(point); + } + + public void checkVisibility() { + + } + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/lists/items/ControlPanel.java b/src/main/java/com/github/oxygenPlugins/common/gui/lists/items/ControlPanel.java new file mode 100644 index 0000000..c568f22 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/lists/items/ControlPanel.java @@ -0,0 +1,52 @@ +package com.github.oxygenPlugins.common.gui.lists.items; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; + +import javax.swing.JComponent; +import javax.swing.JPanel; + +import com.github.oxygenPlugins.common.gui.lists.items.AbstractListItem.Mouse; +import com.github.oxygenPlugins.common.gui.swing.SwingUtil; + +@SuppressWarnings("rawtypes") +public class ControlPanel extends JPanel { + private static final long serialVersionUID = 651451428874393350L; + private final Mouse mouse; + private GridBagLayout gbl = new GridBagLayout(); + + + public ControlPanel(JComponent comp, Mouse mouse) { + this(mouse); + + this.setMaximumSize(new Dimension(100000, 5)); + this.add(comp); + } + + public ControlPanel(Mouse mouse) { + this.setLayout(gbl); + this.setOpaque(false); + this.mouse = mouse; + + + } + + public void add(JComponent comp, Insets insets){ + this.removeAll(); + SwingUtil.addComponent(this, gbl, comp, 0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, insets); + comp.setSize(new Dimension(comp.getWidth(), 5)); + comp.setOpaque(false); + comp.addMouseListener(mouse); + for (Component childComp : comp.getComponents()) { + childComp.addMouseListener(mouse); + } + this.repaint(); + } + + public void add(JComponent comp) { + this.add(comp, new Insets(0, 0, 0, 0)); + } +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/lists/items/ItemGroup.java b/src/main/java/com/github/oxygenPlugins/common/gui/lists/items/ItemGroup.java new file mode 100644 index 0000000..c511c00 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/lists/items/ItemGroup.java @@ -0,0 +1,172 @@ +package com.github.oxygenPlugins.common.gui.lists.items; + +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; + +import javax.swing.Icon; + +import com.github.oxygenPlugins.common.gui.lists.AbstractList; +import com.github.oxygenPlugins.common.gui.lists.Theme; + + +public abstract class ItemGroup & Comparable> + extends AbstractListItem<_ListGroupNode> { + + private static final long serialVersionUID = -3830254020006810672L; + + protected final ArrayList items; + + private boolean isExpanded = true; + + private final AbstractList parentList; + private final ArrayList> subGroups; + + private CollapseListener collapseListener; + + public ItemGroup(_ListGroupNode node, ArrayList items, + ArrayList> subGroups, + int level, AbstractList parentList, Icon defaultIcon, Theme theme, boolean collapse) { + super(node, level, defaultIcon, theme); + + this.items = items; + this.subGroups = subGroups; + this.parentList = parentList; + + setLevel(level); + + this.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + selectSubItems(e); + super.mouseClicked(e); + } + }); + this.addIconMouseAdapter(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent me) { + if (isExpanded) { + collapse(); + } else { + expand(); + } + super.mouseClicked(me); + } + }); + if(collapse){ + this.isExpanded = false; + collapse(); + } + } + + @Override + public void setLevel(int level) { + super.setLevel(level); + + for (ItemGroup subGroup : subGroups) { + subGroup.setLevel(level + 1); + } + for (SubItemType item : items) { + item.setLevel(level + 1); + } + } + + protected void selectSubItems(MouseEvent e) { + ArrayList descItems = getDescandentItems(); + + this.parentList.selectUnselectItem(e, descItems); + } + + private ArrayList getDescandentItems() { + ArrayList descItems = new ArrayList(); + + for (ItemGroup group : this.getSubGroups()) { + descItems.addAll(group.getDescandentItems()); + } + + descItems.addAll(getItems()); + + return descItems; + } + + // @Override + // public Icon getDefaultIcon() { + // // if(this.node.getMessageCount() > 0){ + // // return ema.getIcon(IconMap.MESSAGE_GROUP_FAILED); + // // } else { + // // return ema.getIcon(IconMap.MESSAGE_GROUP_SUCCEDED); + // // } + // return null; + // } + + public ArrayList getItems() { + ArrayList subItems = new ArrayList(); + // for (ItemGroup group : subGroups) { + // subItems.addAll(group.getItems()); + // } + subItems.addAll(items); + return subItems; + } + + public void expand() { + for (ItemGroup group : subGroups) { + group.setVisible(true); + group.expand(); + } + for (SubItemType subItem : this.items) { + subItem.setVisible(true); + } + if(collapseListener != null) + collapseListener.expand(); + this.isExpanded = true; + }; + + public void collapse() { + for (ItemGroup group : subGroups) { + group.setVisible(false); + group.collapse(); + } + for (SubItemType subItem : this.items) { + subItem.setVisible(false); + } + if(collapseListener != null) + collapseListener.collapse(); + this.isExpanded = false; + } + + public static interface CollapseListener { + public void collapse(); + public void expand(); + } + + public void setCollapseListener(CollapseListener listener){ + this.collapseListener = listener; + } + public void removeCollapseListener(){ + this.collapseListener = null; + } + + public ArrayList> getSubGroups() { + return this.subGroups; + } + + @Override + public void checkVisibility() { + if(!this.isExpanded){ + this.setVisible(true); + } else { + boolean isOneVisible = false; + for (SubItemType subItem : this.getItems()) { + if(subItem.isVisible()){ + isOneVisible = true; + } + } + this.setVisible(isOneVisible); + } + } + + public boolean isExpanded() { + return this.isExpanded; + } + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/lists/items/_ListGroupNode.java b/src/main/java/com/github/oxygenPlugins/common/gui/lists/items/_ListGroupNode.java new file mode 100644 index 0000000..1e4a482 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/lists/items/_ListGroupNode.java @@ -0,0 +1,5 @@ +package com.github.oxygenPlugins.common.gui.lists.items; + +public interface _ListGroupNode extends _ListNode{ + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/lists/items/_ListNode.java b/src/main/java/com/github/oxygenPlugins/common/gui/lists/items/_ListNode.java new file mode 100644 index 0000000..49a0003 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/lists/items/_ListNode.java @@ -0,0 +1,11 @@ +package com.github.oxygenPlugins.common.gui.lists.items; + +import java.io.IOException; + +import javax.swing.Icon; + +public interface _ListNode { + boolean hasIcon(); + Icon getIcon() throws IOException; + void setIcon(Icon icon); +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/process/ProgressListener.java b/src/main/java/com/github/oxygenPlugins/common/gui/process/ProgressListener.java new file mode 100644 index 0000000..59fe0d8 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/process/ProgressListener.java @@ -0,0 +1,83 @@ +package com.github.oxygenPlugins.common.gui.process; + +import javax.swing.JFrame; + +import com.nkutsche.common.process.exceptions.CancelException; +import com.nkutsche.common.process.exceptions.ErrorViewer; +import com.nkutsche.common.process.log.ProcessLoger; + + +public class ProgressListener implements ProcessLoger { + private final int steps; + private ProgressViewer progressViewer; + private int currentStep = 1; + private final int delayOnEnd; + private final ErrorViewer errorViewer; + + public ProgressListener(int steps, String description, ErrorViewer ev) throws CancelException{ + this(steps, description, ev, 1000); + } + + public ProgressListener(int steps, String description, ErrorViewer ev, int delayOnEnd) throws CancelException{ + this.steps = steps; + this.delayOnEnd = delayOnEnd; + this.progressViewer = new ProgressViewer(description, ev); + this.errorViewer = ev; + } + + public ProgressListener(int steps, String description, JFrame parent, ErrorViewer ev) throws CancelException{ + this(steps, description, parent, ev, 1000); + } + + public ProgressListener(int steps, String description, JFrame parent, ErrorViewer ev, int delayOnEnd) throws CancelException{ + this(steps, description, ev, delayOnEnd); + this.progressViewer = new ProgressViewer(description, parent, ev); + } + + @Override + public void log(String message) { + if(!progressViewer.isVisible()){ + progressViewer.start(); + } + progressViewer.setProcessState((currentStep * 100) / steps, message); +// if(currentStep == steps){ +// end(); +// } + currentStep++; + } + + @Override + public void log(String message, boolean taskEnd) { + log(message); + if(taskEnd){ + end(); + } + } + + @Override + public void end() { + // TODO Auto-generated method stub + if(delayOnEnd > 0 && currentStep == steps){ + try { + Thread.sleep(delayOnEnd); + } catch (InterruptedException e) { + } + } + progressViewer.end(); + } + + @Override + public void log(Exception exception) throws CancelException { + errorViewer.viewException(exception); + } + + @Override + public void log(Exception exception, boolean forceEnd) throws CancelException { + this.log(exception); + if(forceEnd){ + this.log(exception.getLocalizedMessage(), true); + } + } + + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/process/ProgressViewer.java b/src/main/java/com/github/oxygenPlugins/common/gui/process/ProgressViewer.java new file mode 100644 index 0000000..f9f8aef --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/process/ProgressViewer.java @@ -0,0 +1,82 @@ +package com.github.oxygenPlugins.common.gui.process; + +import java.awt.Cursor; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; + +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JProgressBar; +import javax.swing.UIManager; + +import com.github.oxygenPlugins.common.gui.swing.SwingUtil; +import com.nkutsche.common.process.exceptions.CancelException; +import com.nkutsche.common.process.exceptions.ErrorViewer; + + + +public class ProgressViewer extends JFrame { + + private static final long serialVersionUID = 3337486025841559125L; + private final JProgressBar bar; + private final GridBagLayout gbl = new GridBagLayout(); + private JLabel procLab = new JLabel(); + private final JFrame parent; + + public ProgressViewer(String title, ErrorViewer errorListener) throws CancelException { + this(title, null, errorListener); + } + + public ProgressViewer(String title, JFrame parent, ErrorViewer errorListener) throws CancelException { + + this.parent = parent; + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception e) { + errorListener.viewException(e); + } + this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + this.bar = new JProgressBar(0, 100); + this.bar.setStringPainted(true); + this.setLayout(gbl); + JLabel titleLab = new JLabel(title); + Font defaultFont = titleLab.getFont(); + titleLab.setFont(new Font(defaultFont.getFontName(), Font.BOLD, + defaultFont.getSize())); + + procLab.setFont(new Font(defaultFont.getFontName(), Font.PLAIN, + defaultFont.getSize())); + + SwingUtil.addComponent(this, gbl, titleLab, 0, 0, 1, 1, 1.0, 1.0, + GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, + new Insets(5, 5, 5, 5)); + SwingUtil.addComponent(this, gbl, procLab, 0, 1, 1, 1, 1.0, 1.0, + GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, + new Insets(5, 5, 5, 5)); + SwingUtil.addComponent(this, gbl, bar, 0, 2, 1, 1, 1.0, 1.0, + GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, + new Insets(5, 5, 5, 5)); + + this.setAlwaysOnTop(true); +// this.setUndecorated(true); + } + + public void start(){ + this.pack(); + this.setSize(this.getWidth() * 2, this.getHeight() + 10); + com.github.oxygenPlugins.common.gui.swing.SwingUtil.centerFrame(this, parent); + this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + this.setVisible(true); + } + + public void setProcessState(int progress, String desc){ + this.procLab.setText(desc); + this.bar.setValue(progress); + } + public void end(){ + this.setVisible(false); + } +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/splitPane/CollapsListener.java b/src/main/java/com/github/oxygenPlugins/common/gui/splitPane/CollapsListener.java new file mode 100644 index 0000000..7567753 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/splitPane/CollapsListener.java @@ -0,0 +1,43 @@ +package com.github.oxygenPlugins.common.gui.splitPane; + +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; + +public class CollapsListener implements ComponentListener { + + private final MultiSplit multiSplit; + + public CollapsListener(MultiSplit multiSplit) { + this.multiSplit = multiSplit; + + } + + @Override + public void componentHidden(ComponentEvent arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void componentMoved(ComponentEvent arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void componentResized(ComponentEvent arg0) { + if(multiSplit.isFirstCollapsed()){ + multiSplit.collapseFirst(); + } else if(multiSplit.isSecondCollapsed()){ + multiSplit.collapseSecond(); + } + + } + + @Override + public void componentShown(ComponentEvent arg0) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/splitPane/MultiSplit.java b/src/main/java/com/github/oxygenPlugins/common/gui/splitPane/MultiSplit.java new file mode 100644 index 0000000..c7f9e5d --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/splitPane/MultiSplit.java @@ -0,0 +1,257 @@ +package com.github.oxygenPlugins.common.gui.splitPane; + +import javax.swing.JComponent; +import javax.swing.JSplitPane; + +public class MultiSplit extends JSplitPane { + + private static final long serialVersionUID = -2149523834046794896L; + private final MultiSplit childSplitPane; + private final int orientation; + + private final JComponent child1; + private final JComponent child2; + + private int dividerSize; + + public MultiSplit(int[] orientations, JComponent[] components) { + super(orientations[0]); + this.orientation = orientations[0]; + this.child1 = components[0]; + if (components.length == 2) { + this.childSplitPane = null; + this.child2 = components[1]; + } else { + JComponent[] restComponents = getLastComponents(components); + int[] restOrientations = getLastIntegers(orientations); + this.childSplitPane = new MultiSplit(restOrientations, + restComponents); + this.child2 = this.childSplitPane; + } + setComponets(); + this.addComponentListener(new CollapsListener(this)); + this.setOneTouchExpandable(false); + } + + public MultiSplit(int orientation, JComponent[] components) { + super(orientation); + this.orientation = orientation; + this.child1 = components[0]; + + if (components.length == 2) { + this.childSplitPane = null; + this.child2 = components[1]; + } else { + JComponent[] restComponents = getLastComponents(components); + this.childSplitPane = new MultiSplit(orientation, restComponents); + this.child2 = this.childSplitPane; + } + setComponets(); + this.addComponentListener(new CollapsListener(this)); + this.setOneTouchExpandable(false); + } + + public MultiSplit(int orientation, JComponent child, MultiSplit childSplitPane){ + super(orientation); + this.orientation = orientation; + this.child1 = child; + this.childSplitPane = childSplitPane; + this.child2 = childSplitPane; + setComponets(); + this.addComponentListener(new CollapsListener(this)); + this.setOneTouchExpandable(false); + } + + + private void setComponets() { + if (this.orientation == JSplitPane.HORIZONTAL_SPLIT) { + this.setLeftComponent(this.child1); + this.setRightComponent(this.child2); + } else { + this.setTopComponent(this.child1); + this.setBottomComponent(this.child2); + } + + } + + + + public void show(JComponent comp) { + if(this.child1 == comp && isFirstCollapsed()){ + expand(); + } else if(this.child2 == comp){ + if(isSecondCollapsed()){ + expand(); + } + } else if (isSecondCollapsed()){ + expand(); + } else if(this.childSplitPane != null){ + this.childSplitPane.show(comp); + } + } + + private boolean isFirstCollapsed = false; + private boolean isSecondeCollapsed = false; + @SuppressWarnings("unused") + private double lastDividerLocation = 0.0; + + protected void expand() { + this.setDividerLocation(this.getResizeWeight()); + this.isFirstCollapsed = false; + this.isSecondeCollapsed = false; + super.setDividerSize(dividerSize); + } + + protected void collapseFirst(){ + setLastDividerLocation(); + this.isFirstCollapsed = true; + this.isSecondeCollapsed = false; + this.setDividerLocation(0.0); + super.setDividerSize(0); + } + + protected void collapseSecond(){ + if(!this.isSecondeCollapsed){ + setLastDividerLocation(); + } + this.isFirstCollapsed = false; + this.isSecondeCollapsed = true; + this.setDividerLocation(1.0); + super.setDividerSize(0); + } + + public void setLastDividerLocation() { + int size = this.orientation == JSplitPane.HORIZONTAL_SPLIT ? this.getWidth() : this.getHeight(); + if(size == 0){ + this.lastDividerLocation = this.getResizeWeight(); + } else { + this.lastDividerLocation = this.getDividerLocation() / size; + } + } + + protected boolean isFirstCollapsed() { + return this.isFirstCollapsed; + } + protected boolean isSecondCollapsed() { + return this.isSecondeCollapsed; + } + + public void hide(JComponent comp) { + if (this.child1 == comp) { + collapseFirst(); + } else if (this.child2 == comp) { + collapseSecond(); + } else if (this.childSplitPane != null) { + this.childSplitPane.hide(comp); + } + } + + public void hideFrom(JComponent comp) { + if (this.child1 == comp) { + return; + } else if (this.child2 == comp) { + hide(comp); + } else if (this.childSplitPane != null) { + if (this.childSplitPane.getFirstChild() == comp) { + collapseSecond(); + } else { + this.childSplitPane.hideFrom(comp); + } + } + } + + private JComponent getFirstChild() { + return this.child1; + } + + public void setResizeWeight(double[] weights){ + this.setResizeWeight(weights[0] / sum(weights)); + + if(this.childSplitPane != null){ + this.childSplitPane.setResizeWeight(getLastDoubles(weights)); + } + } + + +// +// Overrides +// + + @Override + public void setContinuousLayout(boolean newContinuousLayout) { + if (this.childSplitPane != null) { + this.childSplitPane.setContinuousLayout(newContinuousLayout); + } + // TODO Auto-generated method stub + super.setContinuousLayout(newContinuousLayout); + } + + + +// @Override +// public void setOneTouchExpandable(boolean newValue) { +// if (this.childSplitPane != null) { +// this.childSplitPane.setOneTouchExpandable(newValue); +// } +// // TODO Auto-generated method stub +// super.setOneTouchExpandable(newValue); +// } + + @Override + public void setDividerSize(int newSize) { + this.dividerSize = newSize; + if (this.childSplitPane != null) { + this.childSplitPane.setDividerSize(newSize); + } + // TODO Auto-generated method stub + super.setDividerSize(newSize); + } + + +// +// Static methods +// + + + private static double sum(double[] values){ + double sum = 0.0; + for (int i = 0; i < values.length; i++) { + sum += values[i]; + } + return sum; + } + + private static JComponent[] getLastComponents(JComponent[] components) { + if (components.length == 1) { + return null; + } + JComponent[] newComp = new JComponent[components.length - 1]; + for (int i = 0; i < newComp.length; i++) { + newComp[i] = components[i + 1]; + } + return newComp; + } + + private int[] getLastIntegers(int[] ints) { + if (ints.length == 1) { + return null; + } + int[] newInts = new int[ints.length - 1]; + for (int i = 0; i < newInts.length; i++) { + newInts[i] = ints[i + 1]; + } + return newInts; + } + + private double[] getLastDoubles(double[] doubles) { + if (doubles.length == 1) { + return null; + } + double[] newDoubles = new double[doubles.length - 1]; + for (int i = 0; i < newDoubles.length; i++) { + newDoubles[i] = doubles[i + 1]; + } + return newDoubles; + } + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/swing/FileDragSource.java b/src/main/java/com/github/oxygenPlugins/common/gui/swing/FileDragSource.java new file mode 100644 index 0000000..c759220 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/swing/FileDragSource.java @@ -0,0 +1,89 @@ +package com.github.oxygenPlugins.common.gui.swing; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceDragEvent; +import java.awt.dnd.DragSourceDropEvent; +import java.awt.dnd.DragSourceEvent; +import java.awt.dnd.DragSourceListener; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.JPanel; + +public abstract class FileDragSource implements DragGestureListener, + DragSourceListener { + + public FileDragSource(JPanel panel){ + DragSource dragSource = DragSource.getDefaultDragSource(); + dragSource.createDefaultDragGestureRecognizer(panel, DnDConstants.ACTION_COPY, this); + } + + + public abstract File[] getDragedFileList(); + + @SuppressWarnings({ "unchecked", "rawtypes" }) + class FileListTransferable implements Transferable { + public FileListTransferable(File[] files) { + fileList = new ArrayList(); + for (int i = 0; i < files.length; i++) { + fileList.add(files[i]); + } + } + + // Implementation of the Transferable interface + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[] { DataFlavor.javaFileListFlavor }; + } + + public boolean isDataFlavorSupported(DataFlavor fl) { + return fl.equals(DataFlavor.javaFileListFlavor); + } + + public Object getTransferData(DataFlavor fl) { + if (!isDataFlavorSupported(fl)) { + return null; + } + + return fileList; + } + + List fileList; // The list of files + } + + @Override + public void dragGestureRecognized(DragGestureEvent dge) { + File[] fileList = getDragedFileList(); + if(fileList.length > 0){ + Transferable transferable = new FileListTransferable(getDragedFileList()); + dge.startDrag(null, transferable, this); + } + } + + @Override + public void dragDropEnd(DragSourceDropEvent arg0) { + } + + @Override + public void dragEnter(DragSourceDragEvent arg0) { + } + + @Override + public void dragExit(DragSourceEvent arg0) { + } + + @Override + public void dragOver(DragSourceDragEvent arg0) { + } + + @Override + public void dropActionChanged(DragSourceDragEvent arg0) { + // TODO Auto-generated method stub + + } +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/swing/FileDropTarget.java b/src/main/java/com/github/oxygenPlugins/common/gui/swing/FileDropTarget.java new file mode 100644 index 0000000..24d243b --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/swing/FileDropTarget.java @@ -0,0 +1,106 @@ +package com.github.oxygenPlugins.common.gui.swing; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetDragEvent; +import java.awt.dnd.DropTargetDropEvent; +import java.awt.dnd.DropTargetEvent; +import java.awt.dnd.DropTargetListener; +import java.io.File; +import java.util.List; + +import javax.swing.JPanel; + +public abstract class FileDropTarget implements DragGestureListener, + DropTargetListener { + + public FileDropTarget(JPanel panel) { + new DropTarget(panel, this); + DragSource dragSource = DragSource.getDefaultDragSource(); + dragSource.createDefaultDragGestureRecognizer(panel, DnDConstants.ACTION_COPY, this); + } + +// public abstract File[] getDragedFileList(); + + + @SuppressWarnings("unchecked") + @Override + public void drop(DropTargetDropEvent dte) { + dte.acceptDrop(DnDConstants.ACTION_COPY); + + // Get the transfer which can provide the dropped item data + Transferable transferable = dte.getTransferable(); + + // Get the data formats of the dropped item + DataFlavor[] flavors = transferable.getTransferDataFlavors(); + + for (DataFlavor flavor : flavors) { + + try { + + // If the drop items are files + if (flavor.isFlavorJavaFileListType()) { + + // Get all of the dropped files + List files = (List) transferable + .getTransferData(flavor); + + // Loop them through + this.receiveFiles(files); + + } + + } catch (Exception e) { + + // Print out the error stack + e.printStackTrace(); + + } + } + + // Inform that the drop is complete + dte.dropComplete(true); + + } + + + public abstract void receiveFiles(List files); + + @Override + public void dragEnter(DropTargetDragEvent arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void dragExit(DropTargetEvent arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void dragOver(DropTargetDragEvent arg0) { + // TODO Auto-generated method stub + + } + + + + @Override + public void dropActionChanged(DropTargetDragEvent arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void dragGestureRecognized(DragGestureEvent arg0) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/swing/SwingUtil.java b/src/main/java/com/github/oxygenPlugins/common/gui/swing/SwingUtil.java new file mode 100644 index 0000000..da7f6d3 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/swing/SwingUtil.java @@ -0,0 +1,68 @@ +package com.github.oxygenPlugins.common.gui.swing; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Toolkit; +import java.awt.Window; + + +public class SwingUtil { + + public static void addComponent(final Container cont, final GridBagLayout gbl, final Component c, final int x, final int y, + final int width, final int height, final double weightx, final double weighty) { + addComponent(cont, gbl, c, x, y, width, height, weightx, weighty, GridBagConstraints.NORTH, GridBagConstraints.BOTH); + } + + public static void addComponent(final Container cont, final GridBagLayout gbl, final Component c, final int x, final int y, + final int width, final int height, final double weightx, final double weighty, final int anchor, final int fill) { + addComponent(cont, gbl, c, x, y, width, height, weightx, weighty, anchor, fill, new Insets(0, 0, 0, 0)); + } + + public static void addComponent(final Container container, final GridBagLayout gbl, final Component c, final int x, final int y, + final int width, final int height, final double weightx, final double weighty, final int anchor, final int fill, + final Insets insets) { + final GridBagConstraints gbc = new GridBagConstraints(); + gbc.fill = fill; + gbc.gridx = x; + gbc.gridy = y; + gbc.gridwidth = width; + gbc.gridheight = height; + gbc.weightx = weightx; + gbc.weighty = weighty; + gbc.anchor = anchor; + gbc.insets = insets; + gbl.setConstraints(c, gbc); + container.add(c); + } + public static void centerFrame(final Window frame) { + final Rectangle bounds = frame.getBounds(); + final Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); + bounds.x = (screen.width / 2) - (bounds.width / 2); + bounds.y = (screen.height / 2) - (bounds.height / 2); + frame.setBounds(bounds); + } + +// public static void centerFrame(final Window frame, final Window parentFrame) { +// final Rectangle bounds = frame.getBounds(); +// final Rectangle parentBounds = parentFrame.getBounds(); +// bounds.x = (parentBounds.width / 2) - (bounds.width / 2) + parentBounds.x; +// bounds.y = (parentBounds.height / 2) - (bounds.height / 2) + parentBounds.y; +// frame.setBounds(bounds); +// } +// + public static void centerFrame(final Window frame, Window owner){ + if(owner != null){ + Point ownerLoc = owner.getLocation(); + frame.setLocation(ownerLoc.x + (owner.getWidth() / 2) - (frame.getWidth() / 2), + ownerLoc.y + (owner.getHeight() / 2) - (frame.getHeight() / 2)); + } else { + centerFrame(frame); + } + } +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/swing/WrapLayout.java b/src/main/java/com/github/oxygenPlugins/common/gui/swing/WrapLayout.java new file mode 100644 index 0000000..d51a471 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/swing/WrapLayout.java @@ -0,0 +1,198 @@ +package com.github.oxygenPlugins.common.gui.swing; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Insets; + +import javax.swing.JScrollPane; +import javax.swing.SwingUtilities; + +/** + * FlowLayout subclass that fully supports wrapping of components. + */ +public class WrapLayout extends FlowLayout +{ + private static final long serialVersionUID = 2439203958402278119L; +// private Dimension preferredLayoutSize; + + /** + * Constructs a new WrapLayout with a left + * alignment and a default 5-unit horizontal and vertical gap. + */ + public WrapLayout() + { + super(); + } + + /** + * Constructs a new FlowLayout with the specified + * alignment and a default 5-unit horizontal and vertical gap. + * The value of the alignment argument must be one of + * WrapLayout, WrapLayout, + * or WrapLayout. + * @param align the alignment value + */ + public WrapLayout(int align) + { + super(align); + } + + /** + * Creates a new flow layout manager with the indicated alignment + * and the indicated horizontal and vertical gaps. + *

+ * The value of the alignment argument must be one of + * WrapLayout, WrapLayout, + * or WrapLayout. + * @param align the alignment value + * @param hgap the horizontal gap between components + * @param vgap the vertical gap between components + */ + public WrapLayout(int align, int hgap, int vgap) + { + super(align, hgap, vgap); + } + + /** + * Returns the preferred dimensions for this layout given the + * visible components in the specified target container. + * @param target the component which needs to be laid out + * @return the preferred dimensions to lay out the + * subcomponents of the specified container + */ + @Override + public Dimension preferredLayoutSize(Container target) + { + return layoutSize(target, true); + } + + /** + * Returns the minimum dimensions needed to layout the visible + * components contained in the specified target container. + * @param target the component which needs to be laid out + * @return the minimum dimensions to lay out the + * subcomponents of the specified container + */ + @Override + public Dimension minimumLayoutSize(Container target) + { + Dimension minimum = layoutSize(target, false); + minimum.width -= (getHgap() + 1); + return minimum; + } + + /** + * Returns the minimum or preferred dimension needed to layout the target + * container. + * + * @param target target to get layout size for + * @param preferred should preferred size be calculated + * @return the dimension to layout the target container + */ + private Dimension layoutSize(Container target, boolean preferred) + { + synchronized (target.getTreeLock()) + { + // Each row must fit with the width allocated to the containter. + // When the container width = 0, the preferred width of the container + // has not yet been calculated so lets ask for the maximum. + + int targetWidth = target.getSize().width; + Container container = target; + + while (container.getSize().width == 0 && container.getParent() != null) + { + container = container.getParent(); + } + + targetWidth = container.getSize().width; + + if (targetWidth == 0) + targetWidth = Integer.MAX_VALUE; + + int hgap = getHgap(); + int vgap = getVgap(); + Insets insets = target.getInsets(); + int horizontalInsetsAndGap = insets.left + insets.right + (hgap * 2); + int maxWidth = targetWidth - horizontalInsetsAndGap; + + // Fit components into the allowed width + + Dimension dim = new Dimension(0, 0); + int rowWidth = 0; + int rowHeight = 0; + + int nmembers = target.getComponentCount(); + + for (int i = 0; i < nmembers; i++) + { + Component m = target.getComponent(i); + + if (m.isVisible()) + { + Dimension d = preferred ? m.getPreferredSize() : m.getMinimumSize(); + + // Can't add the component to current row. Start a new row. + + if (rowWidth + d.width > maxWidth) + { + addRow(dim, rowWidth, rowHeight); + rowWidth = 0; + rowHeight = 0; + } + + // Add a horizontal gap for all components after the first + + if (rowWidth != 0) + { + rowWidth += hgap; + } + + rowWidth += d.width; + rowHeight = Math.max(rowHeight, d.height); + } + } + + addRow(dim, rowWidth, rowHeight); + + dim.width += horizontalInsetsAndGap; + dim.height += insets.top + insets.bottom + vgap * 2; + + // When using a scroll pane or the DecoratedLookAndFeel we need to + // make sure the preferred size is less than the size of the + // target containter so shrinking the container size works + // correctly. Removing the horizontal gap is an easy way to do this. + + Container scrollPane = SwingUtilities.getAncestorOfClass(JScrollPane.class, target); + + if (scrollPane != null && target.isValid()) + { + dim.width -= (hgap + 1); + } + + return dim; + } + } + + /* + * A new row has been completed. Use the dimensions of this row + * to update the preferred size for the container. + * + * @param dim update the width and height when appropriate + * @param rowWidth the width of the row to add + * @param rowHeight the height of the row to add + */ + private void addRow(Dimension dim, int rowWidth, int rowHeight) + { + dim.width = Math.max(dim.width, rowWidth); + + if (dim.height > 0) + { + dim.height += getVgap(); + } + + dim.height += rowHeight; + } +} + diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/BooleanVerifier.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/BooleanVerifier.java new file mode 100644 index 0000000..041d603 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/BooleanVerifier.java @@ -0,0 +1,35 @@ +package com.github.oxygenPlugins.common.gui.types; + +import java.awt.Container; + +import javax.swing.JFormattedTextField; + +import com.github.oxygenPlugins.common.gui.types.panels.BooleanPanel; +import com.github.oxygenPlugins.common.gui.types.panels.BooleanPanel2; +import com.github.oxygenPlugins.common.gui.types.panels.StringPanel; + +public class BooleanVerifier extends ValidCharVerifier { + public BooleanVerifier() { + this(""); + } + public BooleanVerifier(String invalidStrings){ + this(invalidStrings, ""); + } + public BooleanVerifier(String invalidStrings, String invalidStarts){ + super(invalidStrings, invalidStarts, false); + } + + @Override + public void setVerifier(JFormattedTextField field, Container owner) { + BooleanPanel2 sp = new BooleanPanel2(field, owner); +// field.removeFocusListener(sp); + field.addMouseListener(sp); +// field.removeFocusListener(sp); +// field.addFocusListener(sp); + super.setVerifier(field, owner); + } + @Override + public _Verifier getNewInstance() { + return new BooleanVerifier(); + } +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/CalendarTimeVerifier.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/CalendarTimeVerifier.java new file mode 100644 index 0000000..e0fbdb8 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/CalendarTimeVerifier.java @@ -0,0 +1,28 @@ +package com.github.oxygenPlugins.common.gui.types; + +import java.awt.Container; + +import javax.swing.JFormattedTextField; + +import com.github.oxygenPlugins.common.gui.types.panels.CalendarTimePanel2; + +public class CalendarTimeVerifier implements _Verifier { + + + @Override + public void setVerifier(JFormattedTextField field, Container owner) { + field.addMouseListener(new CalendarTimePanel2(field, 11, owner, true)); + } + + @Override + public _Verifier getNewInstance() { + // TODO Auto-generated method stub + return new CalendarTimeVerifier(); + } + + @Override + public void setVerifier(JFormattedTextField field, Container owner, boolean entryHelp) { + setVerifier(field, owner); + } + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/CalendarVerifier.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/CalendarVerifier.java new file mode 100644 index 0000000..dedacc8 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/CalendarVerifier.java @@ -0,0 +1,28 @@ +package com.github.oxygenPlugins.common.gui.types; + +import java.awt.Container; + +import javax.swing.JFormattedTextField; + +import com.github.oxygenPlugins.common.gui.types.panels.CalendarPanel2; + +public class CalendarVerifier implements _Verifier { + + + @Override + public void setVerifier(JFormattedTextField field, Container owner) { + field.addMouseListener(new CalendarPanel2(field, 11, owner)); + } + + @Override + public _Verifier getNewInstance() { + // TODO Auto-generated method stub + return new CalendarVerifier(); + } + + @Override + public void setVerifier(JFormattedTextField field, Container owner, boolean entryHelp) { + setVerifier(field, owner); + } + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/ColorVerifier.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/ColorVerifier.java new file mode 100644 index 0000000..c7f78ab --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/ColorVerifier.java @@ -0,0 +1,45 @@ +package com.github.oxygenPlugins.common.gui.types; + + +import java.awt.Color; +import java.awt.Container; +import java.awt.event.KeyEvent; + +import javax.swing.JFormattedTextField; + +import com.github.oxygenPlugins.common.gui.types.panels.ColorPanel; + +public class ColorVerifier extends ValidCharVerifier { + + public ColorVerifier() { + super("0123456789abcdefABCDEF", ""); + } + @Override + public void setVerifier(JFormattedTextField field, Container owner) { + field.addMouseListener(new ColorPanel(field, owner)); + super.setVerifier(field, owner); + } + + + + public void keyReleased(KeyEvent keyEvent) { + super.keyTyped(keyEvent); + JFormattedTextField field = this.getField(); + String code = field.getText(); + Color c = field.getBackground(); + if (code.replaceAll("[\\dabcdefABCDEF]", "").equals("") + && code.length() == 6) { + c = Color.decode("#" + code); + } + field.setBackground(c); + if(c.getRed()+ c.getGreen() * 1.5 < 334) + field.setForeground(Color.WHITE); + else + field.setForeground(Color.BLACK); + field.repaint(); + } + @Override + public _Verifier getNewInstance() { + return new ColorVerifier(); + } +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/IntegerAreaVerifier.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/IntegerAreaVerifier.java new file mode 100644 index 0000000..d6d6699 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/IntegerAreaVerifier.java @@ -0,0 +1,90 @@ +package com.github.oxygenPlugins.common.gui.types; + + +import java.awt.Container; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; + +import javax.swing.JFormattedTextField; + +import com.github.oxygenPlugins.common.gui.types.panels.StringPanel; + +public class IntegerAreaVerifier implements _Verifier, KeyListener { + + protected final char[] validChars = "0123456789".toCharArray(); + private final int start; + private final int end; + + protected JFormattedTextField field = new JFormattedTextField(); + public IntegerAreaVerifier(int end) { + this(0, end); + } + public IntegerAreaVerifier(int start, int end) { + this.start = start; + this.end = end; + + } + + + + @Override + public void setVerifier(JFormattedTextField field, Container owner) { + this.field = field; + field.addKeyListener(this); + } + protected JFormattedTextField getField(){ + return this.field; + } + + public void keyReleased(KeyEvent ke) {} + public void keyTyped(KeyEvent keyEvent) { + // TODO Auto-generated method stub +// int pos = field.getCaret().getMark(); + int selStart = field.getSelectionStart(); + int selEnd = field.getSelectionEnd(); + char insert = keyEvent.getKeyChar(); + + boolean consume = true; + String newValue = field.getText(); + newValue = newValue.substring(0, selStart) + keyEvent.getKeyChar() + newValue.substring(selEnd); + + for (char valChar : this.validChars) { + if(valChar == insert){ + consume = false; + break; + } + } + if(consume){ + keyEvent.consume(); + } else { + int newValInt = Integer.parseInt(newValue); + if(newValInt > end || newValInt < start){ + keyEvent.consume(); + } + } + + + System.out.println(newValue); +// System.out.println("pos: " + pos); +// System.out.println("selStart: " + selStart); +// System.out.println("selEnd: " + selEnd); + + } + @Override + public void keyPressed(KeyEvent arg0) {} + + @Override + public _Verifier getNewInstance() { +// if(this instanceof IntegerVerifier) +// return new IntegerVerifier(String.copyValueOf(validChars), String.copyValueOf(startChars)); + return new IntegerAreaVerifier(start, end); + } + + @Override + public void setVerifier(JFormattedTextField field, Container owner, boolean entryHelp) { + if(entryHelp) + field.addMouseListener(new StringPanel(field, this, owner)); + setVerifier(field, owner); + } + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/IntegerVerifier.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/IntegerVerifier.java new file mode 100644 index 0000000..84ee439 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/IntegerVerifier.java @@ -0,0 +1,39 @@ +package com.github.oxygenPlugins.common.gui.types; + + +import java.awt.Container; + +import javax.swing.JFormattedTextField; + +import com.github.oxygenPlugins.common.gui.types.panels.StringPanel; + +public class IntegerVerifier extends ValidCharVerifier { + private final static String digits = "0123456789"; + public IntegerVerifier() { + this(""); + } + public IntegerVerifier(String vddValidStrings){ + this(digits + vddValidStrings, ""); + } + public IntegerVerifier(String vddValidStrings, String startChars){ + super(digits + vddValidStrings, startChars); + } + + @Override + public void setVerifier(JFormattedTextField field, Container owner) { + setVerifier(field, owner, true); + } + + @Override + public void setVerifier(JFormattedTextField field, Container owner, boolean entryHelp) { + if(entryHelp){ + field.addMouseListener(new StringPanel(field, this, owner)); + } + super.setVerifier(field, owner); + } + + @Override + public _Verifier getNewInstance() { + return new IntegerVerifier(String.copyValueOf(validChars), String.copyValueOf(startChars)); + } +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/MultiChoiceVerifier.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/MultiChoiceVerifier.java new file mode 100644 index 0000000..1d2cb8c --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/MultiChoiceVerifier.java @@ -0,0 +1,31 @@ +package com.github.oxygenPlugins.common.gui.types; + +import java.awt.Container; + +import javax.swing.JFormattedTextField; + +import com.github.oxygenPlugins.common.gui.types.panels.BooleanPanel; +import com.github.oxygenPlugins.common.gui.types.panels.BooleanPanel2; +import com.github.oxygenPlugins.common.gui.types.panels.MultiChoicePanel; +import com.github.oxygenPlugins.common.gui.types.panels.StringPanel; + +public class MultiChoiceVerifier extends ValidCharVerifier { + private final String[] values; + private final boolean isNullSelectable; + public MultiChoiceVerifier(String[] values, boolean isNullSelectable){ + super("", "", false); + this.values = values; + this.isNullSelectable = isNullSelectable; + } + + @Override + public void setVerifier(JFormattedTextField field, Container owner) { + MultiChoicePanel sp = new MultiChoicePanel(field, owner, this.values, this.isNullSelectable); + field.addMouseListener(sp); + super.setVerifier(field, owner); + } + @Override + public _Verifier getNewInstance() { + return new MultiChoiceVerifier(this.values, this.isNullSelectable); + } +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/PassVerifier.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/PassVerifier.java new file mode 100644 index 0000000..c3b0f6c --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/PassVerifier.java @@ -0,0 +1,56 @@ +package com.github.oxygenPlugins.common.gui.types; + +import java.awt.Color; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.text.ParseException; +import java.util.regex.Pattern; + +import javax.swing.InputVerifier; +import javax.swing.JComponent; +import javax.swing.JFormattedTextField; +import javax.swing.JFrame; +import javax.swing.JTextField; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +import com.github.oxygenPlugins.common.gui.swing.SwingUtil; +import com.github.oxygenPlugins.common.gui.types.converter.TypeConverter; + + + +class PassVerifier extends InputVerifier { + public boolean verify(JComponent input) { + JTextField tf = (JTextField) input; + return Pattern.matches("\\d*", tf.getText()); + } + + public static void main(String[] args) throws ClassNotFoundException, + InstantiationException, IllegalAccessException, + UnsupportedLookAndFeelException, ParseException { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + JFrame frame = new JFrame("number"); + JFormattedTextField stringField = new JFormattedTextField(); + JFormattedTextField intField = new JFormattedTextField(); + JFormattedTextField dateField = new JFormattedTextField(); + VerifierFactory.addVerifier(new TypeConverter("abc"), stringField, frame); + VerifierFactory.addVerifier(new TypeConverter("int"), intField, frame); + VerifierFactory.addVerifier(new TypeConverter("date"), dateField, frame); + + + + GridBagLayout gbl = new GridBagLayout(); + frame.setLayout(gbl); + SwingUtil.addComponent(frame, gbl, stringField, 0, 0, 1, 1, 1.0, 1.0, + GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL); + SwingUtil.addComponent(frame, gbl, intField, 0, 1, 1, 1, 1.0, 1.0, + GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL); + SwingUtil.addComponent(frame, gbl, dateField, 0, 2, 1, 1, 1.0, 1.0, + GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL); + intField.getParent().setBackground(Color.WHITE); + intField.setInputVerifier(new PassVerifier()); + frame.setSize(300, 400); + frame.setVisible(true); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + } +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/StringVerifier.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/StringVerifier.java new file mode 100644 index 0000000..68f7d4f --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/StringVerifier.java @@ -0,0 +1,33 @@ +package com.github.oxygenPlugins.common.gui.types; + +import java.awt.Container; + +import javax.swing.JFormattedTextField; + +import com.github.oxygenPlugins.common.gui.types.panels.StringPanel; + +public class StringVerifier extends ValidCharVerifier { + public StringVerifier() { + this(""); + } + public StringVerifier(String invalidStrings){ + this(invalidStrings, ""); + } + public StringVerifier(String invalidStrings, String invalidStarts){ + super(invalidStrings, invalidStarts, false); + } + + @Override + public void setVerifier(JFormattedTextField field, Container owner) { + StringPanel sp = new StringPanel(field, owner); +// field.removeFocusListener(sp); + field.addMouseListener(sp); +// field.removeFocusListener(sp); +// field.addFocusListener(sp); + super.setVerifier(field, owner); + } + @Override + public _Verifier getNewInstance() { + return new StringVerifier(); + } +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/TimeVerifier.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/TimeVerifier.java new file mode 100644 index 0000000..4d9e04d --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/TimeVerifier.java @@ -0,0 +1,28 @@ +package com.github.oxygenPlugins.common.gui.types; + +import java.awt.Container; + +import javax.swing.JFormattedTextField; + +import com.github.oxygenPlugins.common.gui.types.panels.TimePanel; + +public class TimeVerifier implements _Verifier { + + + @Override + public void setVerifier(JFormattedTextField field, Container owner) { + field.addMouseListener(new TimePanel(field, 11, owner)); + } + + @Override + public _Verifier getNewInstance() { + // TODO Auto-generated method stub + return new TimeVerifier(); + } + + @Override + public void setVerifier(JFormattedTextField field, Container owner, boolean entryHelp) { + setVerifier(field, owner); + } + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/ValidCharVerifier.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/ValidCharVerifier.java new file mode 100644 index 0000000..401bd7f --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/ValidCharVerifier.java @@ -0,0 +1,88 @@ +package com.github.oxygenPlugins.common.gui.types; + + +import java.awt.Container; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; + +import javax.swing.JFormattedTextField; + +import com.github.oxygenPlugins.common.gui.types.panels.StringPanel; + +public class ValidCharVerifier implements _Verifier, KeyListener { + protected final char[] validChars; + protected final char[] startChars; + protected JFormattedTextField field = new JFormattedTextField(); + private final boolean charsAreValid; + public ValidCharVerifier(String validStrings, String validStart) { + this(validStrings, validStart, true); + } + public ValidCharVerifier(String validStrings, String validStart, boolean charsAreValid) { + validChars = (validStrings + validStart).toCharArray(); + this.startChars = validStart.toCharArray(); + this.charsAreValid = charsAreValid; + } + + + + @Override + public void setVerifier(JFormattedTextField field, Container owner) { + this.field = field; + field.addKeyListener(this); + } + protected JFormattedTextField getField(){ + return this.field; + } + public void keyReleased(KeyEvent ke) {} + public void keyTyped(KeyEvent keyEvent) { + // TODO Auto-generated method stub + int pos = field.getCaret().getMark(); + int selStart = field.getSelectionStart(); + int selEnd = field.getSelectionEnd(); + boolean consume = charsAreValid; + for (int i = 0; i < validChars.length; i++) { + if (validChars[i] == keyEvent.getKeyChar()) { + consume = !charsAreValid; + break; + } + } + if (pos != 0 && selStart != 0) { + for (int i = 0; i < startChars.length; i++) { + if (startChars[i] == keyEvent.getKeyChar()) { + consume = charsAreValid; + break; + } + } + } + if (pos == 0 && selEnd ==0){ + char[] chars = field.getText().toCharArray(); + for (int i = 0; i < startChars.length; i++) { + + if (chars.length >0 && startChars[i] == chars[0]) { + consume = charsAreValid; + break; + } + } + } + if (consume) + keyEvent.consume(); + } + @Override + public void keyPressed(KeyEvent arg0) {} + + @Override + public _Verifier getNewInstance() { +// if(this instanceof IntegerVerifier) +// return new IntegerVerifier(String.copyValueOf(validChars), String.copyValueOf(startChars)); + return new ValidCharVerifier(String.copyValueOf(validChars), + String.copyValueOf(startChars), charsAreValid); + } + + @Override + public void setVerifier(JFormattedTextField field, Container owner, boolean entryHelp) { + if(entryHelp) + field.addMouseListener(new StringPanel(field, this, owner)); + setVerifier(field, owner); + } + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/VerifierFactory.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/VerifierFactory.java new file mode 100644 index 0000000..7e1cf7f --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/VerifierFactory.java @@ -0,0 +1,68 @@ +package com.github.oxygenPlugins.common.gui.types; + +import java.awt.Container; +import java.util.HashMap; + +import javax.swing.JFormattedTextField; + +import com.github.oxygenPlugins.common.gui.types.converter.EnumTypeConverter; +import com.github.oxygenPlugins.common.gui.types.converter.TypeConverter; + + +public class VerifierFactory { + private static final String DEFAULT_TYPE = "xs:string"; + + public static _Verifier addVerifier(TypeConverter typeConverter, JFormattedTextField field, Container owner) { + return addVerifier(typeConverter, field, owner, true); + } + + public static _Verifier addVerifier(EnumTypeConverter typeConv, JFormattedTextField field, Container owner, boolean entryHelp) { + MultiChoiceVerifier mcVerifier = new MultiChoiceVerifier(typeConv.getEnumValuesAsString(), false); + mcVerifier.setVerifier(field, owner, entryHelp); + return mcVerifier; + } + public static _Verifier addVerifier(TypeConverter typeConv, JFormattedTextField field, Container owner, boolean entryHelp) { + if(typeConv instanceof EnumTypeConverter){ + return addVerifier((EnumTypeConverter) typeConv, field, owner, entryHelp); + } + + String type = typeConv.getType(); + type = type.replaceFirst("[\\?\\*\\+]$", ""); + type = typeVerifierMap.containsKey(type) ? type : DEFAULT_TYPE; + if(typeVerifierMap.containsKey(type)){ +// field.setEditable(false); + _Verifier verifier = typeVerifierMap.get(type).getNewInstance(); + verifier.setVerifier(field, owner, entryHelp); + return verifier; + } + return null; + } + + @SuppressWarnings("unused") + private static String[] types = new String[] { "float", "double", + "boolean", "byte", "QName", "dateTime", "hexBinary", + "base64Binary", "hexBinary", + "unsignedByte", "time", "g", "anySimpleType", "duration", + "NOTATION" }; + private static HashMap typeVerifierMap = new HashMap(); + static { + typeVerifierMap.put(null, new StringVerifier()); + typeVerifierMap.put("xs:string", new StringVerifier()); + typeVerifierMap.put("xs:boolean", new BooleanVerifier()); + typeVerifierMap.put("xs:int", new IntegerVerifier("","+-")); + typeVerifierMap.put("xs:integer", new IntegerVerifier("","+-")); + typeVerifierMap.put("xs:short", new IntegerVerifier("","+-")); + typeVerifierMap.put("xs:long", new IntegerVerifier("","+-")); + typeVerifierMap.put("xs:decimal", new IntegerVerifier(".","+-")); + typeVerifierMap.put("xs:unsignedInt", new IntegerVerifier("","+")); + typeVerifierMap.put("xs:unsignedShort", new IntegerVerifier("","+")); + typeVerifierMap.put("sqf:color", new ColorVerifier()); + typeVerifierMap.put("xs:date", new CalendarVerifier()); + typeVerifierMap.put("xs:dateTime", new CalendarTimeVerifier()); + typeVerifierMap.put("xs:time", new TimeVerifier()); + } + + public static void installVerifier(String type, _Verifier verifier){ + typeVerifierMap.put(type, verifier); + } +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/_Verifier.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/_Verifier.java new file mode 100644 index 0000000..c8f6aee --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/_Verifier.java @@ -0,0 +1,11 @@ +package com.github.oxygenPlugins.common.gui.types; + +import java.awt.Container; + +import javax.swing.JFormattedTextField; + +public interface _Verifier { + public void setVerifier(JFormattedTextField field, Container owner); + public _Verifier getNewInstance(); + void setVerifier(JFormattedTextField field, Container owner, boolean entryHelp); +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/converter/EnumTypeConverter.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/converter/EnumTypeConverter.java new file mode 100644 index 0000000..dbf31d4 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/converter/EnumTypeConverter.java @@ -0,0 +1,42 @@ +package com.github.oxygenPlugins.common.gui.types.converter; + +import javax.xml.xpath.XPathExpressionException; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import com.nkutsche.common.xml.xpath.XPathReader; + +public class EnumTypeConverter extends TypeConverter { + + private final Object[] enumValues; + + public EnumTypeConverter(String type, NodeList values) { + super(type); + XPathReader xpathreader = new XPathReader(); + // E N U M E R A T I O N + enumValues = new Object[values.getLength()]; + for (int i = 0; i < values.getLength(); i++) { + Node enumVal = values.item(i); + try { + enumValues[i] = this.convertValue(xpathreader.getString(".", enumVal)); + } catch (XPathExpressionException e) { + enumValues[i] = null; + } + } + + } + + public Object[] getEnumValues() { + return enumValues; + } + + public String[] getEnumValuesAsString(){ + String[] values = new String[enumValues.length]; + int i = 0; + for (Object val : enumValues) { + values[i++] = this.convertToString(val); + } + return values; + } +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/converter/TypeConverter.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/converter/TypeConverter.java new file mode 100644 index 0000000..e0f2d4a --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/converter/TypeConverter.java @@ -0,0 +1,112 @@ +package com.github.oxygenPlugins.common.gui.types.converter; + +import java.util.HashMap; + +import net.sf.saxon.trans.XPathException; +import net.sf.saxon.type.ValidationException; +import net.sf.saxon.value.DateTimeValue; +import net.sf.saxon.value.DateValue; +import net.sf.saxon.value.TimeValue; + +@SuppressWarnings("rawtypes") +public class TypeConverter { + private String type; + public TypeConverter(String type) { + this.type = type; + + } + + public Object convertValue(String value){ + Object result; + try{ + if(value == null){ + result = null; + } else if (type.equals("xs:dateTime")) { + result = getClass(type).cast(getDate(value)); + } else if (type.equals("xs:time")) { + result = getClass(type).cast(getTime(value)); + } else if (type.equals("xs:date")) { + result = getClass(type).cast(getDate(value)); + } else if (type.equals("xs:dateTime")) { + result = getClass(type).cast(getDateTime(value)); + } else if (type.equals("xs:integer")) { + int valInt = value.equals("") ? 0 : Integer.valueOf(value); + result = getClass(type).cast(valInt); + } else { + result = getClass(type).cast(value); + } + return result; + } catch(ClassCastException e){ + return null; + } + + } + + + private Class getClass(String type){ + if(typeVerifierMap.containsKey(type)){ + return typeVerifierMap.get(type); + } else { + return String.class; + } + } + + private static Object getTime(String value){ + return TimeValue.makeTimeValue(value); + } + private static DateTimeValue getDateTime(String value){ + if(value.contains("T")){ + String[] split = value.split("T"); + try { + return DateTimeValue.makeDateTimeValue(getDate(split[0]), (TimeValue) getTime(split[1])); + } catch (XPathException e) { + } + } + return null; + } + + private static DateValue getDate(String value){ + try { + return new DateValue(value); + } catch (ValidationException e) { + return null; + } + } + + private static HashMap typeVerifierMap = new HashMap(); + static { + typeVerifierMap.put(null, String.class); + typeVerifierMap.put("xs:string", String.class); + typeVerifierMap.put("xs:int", Integer.class); + typeVerifierMap.put("xs:integer", Integer.class); + typeVerifierMap.put("xs:short", Double.class); + typeVerifierMap.put("xs:long", Double.class); + typeVerifierMap.put("xs:decimal", Double.class); + typeVerifierMap.put("xs:unsignedInt", Double.class); + typeVerifierMap.put("xs:unsignedShort", Double.class); + typeVerifierMap.put("sqf:color", String.class); + typeVerifierMap.put("xs:date", DateValue.class); + typeVerifierMap.put("xs:time", TimeValue.class); + typeVerifierMap.put("xs:dateTime", DateTimeValue.class); + } + public String convertToString(Object value) { + if (value instanceof DateValue) { + DateValue dv = (DateValue) value; + return dv.getPrimitiveStringValue().toString(); + } + if (value instanceof TimeValue) { + TimeValue time = (TimeValue) value; + return time.getPrimitiveStringValue().toString(); + } + if (value instanceof DateTimeValue) { + DateTimeValue dateTime = (DateTimeValue) value; + return dateTime.getPrimitiveStringValue().toString(); + } + return value.toString(); + } + + public String getType(){ + return this.type; + } + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/BooleanPanel.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/BooleanPanel.java new file mode 100644 index 0000000..dafef85 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/BooleanPanel.java @@ -0,0 +1,388 @@ +package com.github.oxygenPlugins.common.gui.types.panels; + + +import java.awt.Color; +import java.awt.Container; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowFocusListener; +import java.io.IOException; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JFormattedTextField; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.border.BevelBorder; +import javax.swing.border.Border; + +import com.github.oxygenPlugins.common.gui.images.IconMap; +import com.github.oxygenPlugins.common.gui.swing.SwingUtil; + + +// +public class BooleanPanel extends JPanel implements MouseListener, FocusListener { + private static final long serialVersionUID = 2661956887580911488L; + private final GridBagLayout gbl; + + private final int minWidth = 100; + private final int minHeight = 0; + + private final int maxHeight = 30; + private final int maxWidth = 0; + + private JDialog dialog; +// private final Border defaultBorder = BorderFactory.createBevelBorder( +// BevelBorder.RAISED, new Color(240, 240, 240), new Color(150, 150, +// 150)); + private final Border outlineBorder = BorderFactory.createBevelBorder( + BevelBorder.LOWERED, new Color(110, 110, 110), new Color(200, 200, + 200)); +// private final Border selectBorder = BorderFactory.createBevelBorder( +// BevelBorder.RAISED, new Color(30, 20, 120), +// new Color(110, 100, 200)); + private JFormattedTextField textField; + + private static String[] VALUE_LABELS = new String[]{"", "true", "false"}; + private static String[] VALUE_LABELS_WON = new String[]{"true", "false"}; + private static int VALUE_NULL = 0; + private static int VALUE_TRUE = 1; + private static int VALUE_FALSE = 2; + + private int value; + private final int initialValue; + + private JComboBox entryBox; + private final Container owner; + + private final JPanel buttonPanel = new JPanel(); + private final JButton okBtn; + @SuppressWarnings("unused") + private final JButton cancelBtn; + private final JButton clearBtn; + + private class PanelButton extends JButton{ + private static final long serialVersionUID = 1699184718806511284L; + public PanelButton(Icon i){ + this.setIcon(i); + Dimension dim = new Dimension(i.getIconWidth() + 1, i.getIconHeight() + 1); + this.setMinimumSize(dim); + this.setSize(dim); + } + public PanelButton(String text){ + super(text); + } + } + + public BooleanPanel(final JFormattedTextField field, Container owner) { + this.owner = owner; + this.textField = field; + textField.setHorizontalAlignment(JTextField.CENTER); + if(field.isEnabled()){ + initialValue = field.getText().equals("true") ? VALUE_TRUE : VALUE_FALSE; + value = initialValue; + } else { + initialValue = VALUE_NULL; + value = VALUE_NULL; + } + setBorder(outlineBorder); + setBackground(Color.WHITE); + gbl = new GridBagLayout(); + this.setLayout(gbl); + + GridBagLayout buttonGbl = new GridBagLayout(); + buttonPanel.setLayout(buttonGbl); + buttonPanel.setVisible(false); + + if(IconMap.ICONS == null){ + try { + IconMap.ICONS = new IconMap(); + } catch (IOException e) { + } + } + + if(IconMap.ICONS != null){ + IconMap icons = IconMap.ICONS; + this.okBtn = new PanelButton(icons.getIcon(2, 10)); + this.clearBtn = new PanelButton(icons.getIcon(10, 11)); + this.cancelBtn = new PanelButton(icons.getIcon(0, 10)); + } else { + this.okBtn = new PanelButton("ok"); + this.clearBtn = new PanelButton("x"); + this.cancelBtn = new PanelButton("c"); + } + + this.okBtn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dispose(); + } + }); + + this.clearBtn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dispose(true); + } + }); + +// this.okBtn.setVisible(false); +// this.clearBtn.setVisible(false); +// this.cancelBtn.setVisible(false); + + + entryBox = new JComboBox(value == VALUE_NULL ? VALUE_LABELS : VALUE_LABELS_WON); + entryBox.setSelectedIndex(value); + KeyListener[] kls = textField.getKeyListeners(); + entryBox.addItemListener(new ItemListener() { + + @Override + public void itemStateChanged(ItemEvent ie) { + if(dialog == null) + return; + if(dialog.isVisible()){ + dispose(); + } + } + }); + + entryBox.addKeyListener(new KeyListener() { + @Override + public void keyTyped(KeyEvent e) {} + @Override + public void keyReleased(KeyEvent e) { + if(e.getKeyChar()=='\n'){ + dispose(); + if (textField instanceof FocusTraversalField) { + FocusTraversalField focusField = (FocusTraversalField) textField; + focusField.nextFocus(); + } + } else if(e.getKeyChar() == KeyEvent.VK_ESCAPE){ + dispose(true); + if (textField instanceof FocusTraversalField) { + FocusTraversalField focusField = (FocusTraversalField) textField; + focusField.parentFocus(); + } + } else if(e.getKeyChar() == KeyEvent.VK_TAB){ + if(textField instanceof FocusTraversalField){ + FocusTraversalField focusField = (FocusTraversalField) textField; + + dispose(); + + if(e.isShiftDown()){ + focusField.prevFocus(); + } else { + focusField.nextFocus(); + } + } + } + } + @Override + public void keyPressed(KeyEvent e) {} + }); + + if(textField instanceof FocusTraversalField){ + textField.setFocusable(true); + entryBox.setFocusTraversalKeysEnabled(false); + ((FocusTraversalField) textField).removeAllFocusListener(); + textField.addFocusListener(this); + } + + SwingUtil.addComponent(this, gbl, entryBox, + 0, 0, 1, 1, 1.0, 1.0, + GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(3, 3, 3, 0)); + + +// SwingUtil.addComponent(this, gbl, okBtn, +// 1, 0, 1, 1, 0.0, 1.0, +// GridBagConstraints.NORTHEAST, GridBagConstraints.VERTICAL, new Insets(3, 0, 0, 3)); + + +// SwingUtil.addComponent(this, gbl, cancelBtn, +// 1, 1, 1, 1, 0.0, 1.0, +// GridBagConstraints.EAST, GridBagConstraints.VERTICAL, new Insets(0, 0, 0, 3)); + + SwingUtil.addComponent(this, gbl, clearBtn, + 1, 0, 1, 1, 0.0, 1.0, + GridBagConstraints.SOUTHEAST, GridBagConstraints.VERTICAL, new Insets(0, 0, 3, 3)); + + + MouseListener ml = new MouseListener() { + @Override + public void mouseReleased(MouseEvent arg0) {} + @Override + public void mousePressed(MouseEvent arg0) {} + @Override + public void mouseExited(MouseEvent arg0) { + +// switchToField(); + } + @Override + public void mouseEntered(MouseEvent arg0) { + +// switchToButtons(); + } + @Override + public void mouseClicked(MouseEvent arg0) { + dispose(); + } + }; + + addMouseListener(ml); + } + + + + protected void setText() { + this.textField.setEnabled(true); + this.textField.setText(convert(this.entryBox.getSelectedIndex())); + textField.repaint(); + } + private void getText() { + if(textField.isEnabled()){ + value = convert(textField.getText()); + } else { + value = VALUE_NULL; + } + entryBox.setSelectedItem(textField.getText()); + } + + private String convert(int value){ + return VALUE_LABELS[value]; + } + private int convert(String valueString){ + int i = 0; + for (String label : VALUE_LABELS) { + if(valueString.equals(label)) + return i; + i++; + } + return VALUE_NULL; + } + + @Override + public void mouseClicked(MouseEvent e) { + // TODO Auto-generated method stub + + } + @Override + public void mouseEntered(MouseEvent e) { + + } + @Override + public void mouseExited(MouseEvent e) { + // TODO Auto-generated method stub + + } + @Override + public void mousePressed(MouseEvent e) { + activate(); + } + @Override + public void mouseReleased(MouseEvent e) { + // TODO Auto-generated method stub + + } + private void activate(){ +// if (textField.isEnabled()) { +// if (dialog != null) { +// dispose(); +// } + this.getText(); + + if(dialog == null){ + if(owner instanceof Dialog){ + dialog = new JDialog((Dialog) owner); + } else if(owner instanceof Frame) { + dialog = new JDialog((Frame) owner); + } else if(owner instanceof Window) { + dialog = new JDialog((Window) owner); + } else { + dialog = new JDialog(new JFrame()); + } + } + dialog.addWindowFocusListener(new WindowFocusListener() { + + @Override + public void windowLostFocus(WindowEvent arg0) { + if(dialog != null) + dispose(); + } + + @Override + public void windowGainedFocus(WindowEvent arg0) { + } + }); + dialog.setUndecorated(true); + dialog.setMinimumSize(new Dimension(minWidth, minHeight)); + Point tfLoc = textField.getLocationOnScreen(); + int finalWidth = textField.getWidth() * 2; + int finalHeight = textField.getHeight() * 2; + + finalHeight = this.maxHeight > 0 && this.maxHeight < finalHeight ? this.maxHeight : finalHeight; + finalWidth = this.maxWidth > 0 && this.maxWidth < finalWidth ? this.maxWidth : finalWidth; + + dialog.setMaximumSize(new Dimension(finalWidth, finalHeight)); + + dialog.setSize(finalWidth, finalHeight); + dialog.setLocation(new Point((int) (tfLoc.x - finalWidth * 0.25), + (int) (tfLoc.y - finalHeight * 0.25))); + dialog.add(this); + dialog.setModal(false); + dialog.setVisible(true); +// } + } + + private void dispose(){ + dispose(false); + } + private void dispose(boolean unsetText){ + if(unsetText){ + if(initialValue != VALUE_NULL){ + this.textField.setEnabled(true); + } else { + this.textField.setEnabled(false); + } + this.textField.setText(convert(initialValue)); + this.textField.repaint(); + } else { + this.setText(); + } + if(dialog != null){ + this.dialog.dispose(); + this.dialog = null; + } + } + + @Override + public void focusGained(FocusEvent arg0) { + if(dialog == null){ +// activate(); + } + } + @Override + public void focusLost(FocusEvent arg0) { +// dispose(); + } +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/BooleanPanel2.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/BooleanPanel2.java new file mode 100644 index 0000000..5f29b83 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/BooleanPanel2.java @@ -0,0 +1,14 @@ +package com.github.oxygenPlugins.common.gui.types.panels; + +import java.awt.Container; + +import javax.swing.JFormattedTextField; + +public class BooleanPanel2 extends MultiChoicePanel { + + public BooleanPanel2(JFormattedTextField field, Container owner) { + super(field, owner, new String[]{"true", "false"}); + // TODO Auto-generated constructor stub + } + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/CalendarPanel2.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/CalendarPanel2.java new file mode 100644 index 0000000..a0478a3 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/CalendarPanel2.java @@ -0,0 +1,489 @@ +package com.github.oxygenPlugins.common.gui.types.panels; + + +import java.awt.Color; +import java.awt.Container; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Frame; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Window; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowFocusListener; +import java.io.IOException; +import java.util.Locale; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JDialog; +import javax.swing.JFormattedTextField; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.border.BevelBorder; +import javax.swing.border.Border; + +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; + +import com.github.oxygenPlugins.common.gui.images.IconMap; +import com.github.oxygenPlugins.common.gui.swing.SwingUtil; + + +public class CalendarPanel2 extends JPanel implements MouseListener { + private static final long serialVersionUID = -4261661006435142610L; + private final JDialog dialog; + private final JTextField textField; + + private final Font defFont; + + private final int padding; + private final GridBagLayout gbl = new GridBagLayout(); + + private final int minWidth; + private final int minHeight; + private JPanel contentPanel = new JPanel(); + + private final Border defaultBorder = BorderFactory.createBevelBorder( + BevelBorder.RAISED, new Color(240, 240, 240), new Color(150, 150, + 150)); + private final Border greenBorder = BorderFactory.createBevelBorder( + BevelBorder.LOWERED, new Color(0, 110, 0), new Color(0, 200, + 0)); + private final Border selectBorder = BorderFactory.createBevelBorder( + BevelBorder.RAISED, new Color(30, 20, 120), + new Color(110, 100, 200)); + + public CalendarPanel2(JFormattedTextField field, int fontSize, Container owner) { + + if(owner instanceof Dialog){ + dialog = new JDialog((Dialog) owner); + } else if(owner instanceof Frame) { + dialog = new JDialog((Frame) owner); + } else if(owner instanceof Window) { + dialog = new JDialog((Window) owner); + } else { + dialog = new JDialog(new JFrame()); + } + + this.textField = field; + Font defFont = new JLabel().getFont(); + this.defFont = new Font(defFont.getName(), defFont.getStyle(), fontSize); + + this.minWidth = 25 * fontSize; + this.minHeight = this.minWidth; + this.padding = (int) Math.round(fontSize * 0.75); + this.setLayout(gbl); + + String text = this.textField.getText(); + DateTime actuellDat = convert(text); + buildCalendar(actuellDat, actuellDat); + + this.textField.setFocusable(true); + this.textField.addFocusListener(new FocusListener() { + + @Override + public void focusLost(FocusEvent arg0) { +// textField.setEnabled(false); + } + + @Override + public void focusGained(FocusEvent arg0) { +// textField.setEnabled(true); + + System.out.println("hello calendar field!"); + } + }); + // this.setBackground(Color.RED); + + dialog.addWindowFocusListener(new WindowFocusListener() { + @Override + public void windowLostFocus(WindowEvent arg0) { + dispose(); + } + + @Override + public void windowGainedFocus(WindowEvent arg0) { + } + }); + dialog.addMouseListener(new MouseListener() { + @Override + public void mouseReleased(MouseEvent arg0) { + } + + @Override + public void mousePressed(MouseEvent arg0) { + } + + @Override + public void mouseExited(MouseEvent arg0) { + } + + @Override + public void mouseEntered(MouseEvent arg0) { + } + + @Override + public void mouseClicked(MouseEvent arg0) { + dispose(); + } + }); + dialog.setMinimumSize(new Dimension(minWidth, minHeight)); + dialog.setUndecorated(true); + dialog.add(this); + } + + private void dispose() { + this.dialog.dispose(); + this.textField.setEnabled(true); + } + + @Override + public void mouseClicked(MouseEvent e) { + if (this.dialog.isVisible()) { + dispose(); + } else { + activate(); + } + } + + + + private void activate() { + String text = this.textField.getText(); + DateTime actuellDat = convert(text); + buildCalendar(actuellDat, actuellDat); + +// dialog.setSize(textField.getWidth(), textField.getWidth()); + dialog.setLocation(getDialogBounds()); + // System.out.println(tfLoc.y); + dialog.setModal(false); + dialog.setVisible(true); +// dialog.pack(); + textField.setEnabled(false); + } + + private Point getDialogBounds(){ + + Point tfLoc = textField.getLocationOnScreen(); + Dimension screen = java.awt.Toolkit.getDefaultToolkit().getScreenSize(); + + int x = tfLoc.x + textField.getWidth() - dialog.getWidth(); + x = x < 0 ? 0 : x; + + int y = tfLoc.y + textField.getHeight(); + y = y < 0 ? 0 : y; + + if((x + dialog.getWidth() ) > screen.width){ + x = screen.width - dialog.getWidth(); + } + if((y + dialog.getHeight()) > screen.height){ + y = tfLoc.y - dialog.getHeight(); + } + + return new Point(x, y); + } + + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + } + + @Override + public void mousePressed(MouseEvent e) { + } + + @Override + public void mouseReleased(MouseEvent e) { + } + + private void clear() { + this.remove(contentPanel); + } + + private void buildCalendar(final DateTime actuell, + final DateTime selectedDate) { + clear(); + this.setBorder(defaultBorder); + contentPanel = new JPanel(); + contentPanel.setLayout(gbl); + contentPanel.setBackground(Color.WHITE); + contentPanel.setOpaque(true); + GridBagLayout gblRoot = new GridBagLayout(); + this.setLayout(gblRoot); + SwingUtil.addComponent(this, gblRoot, contentPanel, 0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHEAST, GridBagConstraints.BOTH); + + JPanel head = buildHeader(actuell, selectedDate); + SwingUtil.addComponent(contentPanel, gbl, head, 0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHEAST, GridBagConstraints.BOTH); + + + JPanel body = new JPanel(); + GridBagLayout gblBody = new GridBagLayout(); + body.setLayout(gblBody); + body.setOpaque(false); + SwingUtil.addComponent(contentPanel, gbl, body, 0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHEAST, GridBagConstraints.BOTH); + + final int month = actuell.getMonthOfYear(); + DateTime monthStart = actuell.minusDays(actuell.getDayOfMonth() - 1); + DateTime nextMonth = actuell.plusMonths(1); + DateTime monthEnd = nextMonth.minusDays(nextMonth.getDayOfMonth()); + + int weeks = monthEnd.getWeekOfWeekyear() - monthStart.getWeekOfWeekyear() + 1; + + DateTime start = monthStart.minusDays(monthStart.getDayOfWeek() - 1); + DateTime end = monthEnd.plusDays(7 - monthEnd.getDayOfWeek()); + + weeks = weeks < 0 ? monthEnd.minusDays(monthEnd.getDayOfWeek()).getWeekOfWeekyear() - monthStart.getWeekOfWeekyear() + 2 : weeks; + if (weeks < 0) { + } else if (weeks < 5){ + end = end.plusWeeks(1); + start = start.minusWeeks(1); + } else if(weeks < 6) { + if (monthStart.getDayOfWeek() - 1 > 7 - monthEnd.getDayOfWeek()){ + end = end.plusWeeks(1); + } else { + start = start.minusWeeks(1); + } + } + + + for (int i = 0; i < 7; i++) { + String labelString = start.plusDays(i).toString( + DateTimeFormat.forPattern("E").withLocale(Locale.ENGLISH)); + JLabel weekLabel = new JLabel(labelString.substring(0, 1)); + weekLabel.setFont(defFont); + SwingUtil.addComponent(body, gblBody, weekLabel, i, 0, 1, 1, + 0.0, 0.0, GridBagConstraints.CENTER, + GridBagConstraints.NONE, new Insets(padding, padding, padding, padding)); + } + + int y = 1; + for (DateTime date = start; date.isBefore(end.plusDays(1)); date = date + .plusDays(1)) { + final DateTime finalDate = date; + final DateView label = new DateView(date, selectedDate, month){ + private static final long serialVersionUID = 1L; + @Override + public void performAction() { + confirmDate(finalDate); + } + }; + + SwingUtil.addComponent(body, gblBody, label, + (date.getDayOfWeek() - 1), y, 1, 1, 1.0, 1.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH); + if (date.dayOfWeek().get() == 7) + y++; + } + this.contentPanel.repaint(); + this.repaint(); + this.updateUI(); + } + +// +// H E A D E R +// + private JPanel buildHeader(final DateTime actuell, final DateTime selectedDate){ + JPanel head = new JPanel(); + GridBagLayout gblHead = new GridBagLayout(); + head.setLayout(gblHead); + head.setOpaque(false); + + IconMap icons = null;; + try { + icons = new IconMap(); + } catch (IOException e) { + } + + DateView yearMinus = new DateView(icons.getIcon(10, 13, true)) { + private static final long serialVersionUID = 1L; + + @Override + public void performAction() { + buildCalendar(actuell.minusYears(1), selectedDate); + } + }; + SwingUtil.addComponent(head, gblHead, yearMinus, 0, 0, 1, 1, 0.0, + 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE); + + DateView yearPlus = new DateView(icons.getIcon(8, 13, true)) { + private static final long serialVersionUID = 1L; + + @Override + public void performAction() { + buildCalendar(actuell.plusYears(1), selectedDate); + } + }; + SwingUtil.addComponent(head, gblHead, yearPlus, 2, 0, 1, 1, 0.0, + 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE); + + JLabel yearLabel = new JLabel(actuell.toString(DateTimeFormat + .forPattern("yyyy"))); + yearLabel.setFont(defFont); + yearLabel.setHorizontalAlignment(JLabel.CENTER); + SwingUtil.addComponent(head, gblHead, yearLabel, 1, 0, 1, 1, 1.0, + 1.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL); + + + + DateView monthMinus = new DateView(icons.getIcon(2, 13, true)) { + private static final long serialVersionUID = 1L; + + @Override + public void performAction() { + buildCalendar(actuell.minusMonths(1), selectedDate); + } + }; + SwingUtil.addComponent(head, gblHead, monthMinus, 0, 1, 1, 1, 0.0, + 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE); + + DateView monthPlus = new DateView(icons.getIcon(0, 13, true)) { + private static final long serialVersionUID = 1L; + + @Override + public void performAction() { + buildCalendar(actuell.plusMonths(1), selectedDate); + } + }; + SwingUtil.addComponent(head, gblHead, monthPlus, 2, 1, 1, 1, 0.0, + 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE); + + JLabel monthLabel = new JLabel(actuell.toString(DateTimeFormat + .forPattern("MMMM").withLocale(Locale.ENGLISH))); + monthLabel.setFont(defFont); + monthLabel.setHorizontalAlignment(JLabel.CENTER); + monthLabel.setBackground(Color.WHITE); + monthLabel.setOpaque(true); + SwingUtil.addComponent(head, gblHead, monthLabel, 1, 1, 1, 1, 1.0, + 1.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL); + + + + return head; + } + + private abstract class DateView extends JPanel { + private static final long serialVersionUID = 1L; + private final JLabel label; + private Color foreground; + private Color background = Color.WHITE; + private Border defaultBorder = CalendarPanel2.this.defaultBorder; + + private DateView(int padding){ + this.label = new JLabel(); + this.foreground = Color.BLACK; + this.label.setAlignmentX(JLabel.CENTER_ALIGNMENT); + this.label.setAlignmentY(JLabel.CENTER_ALIGNMENT); + + DateView.this.setSelect(false); + + this.label.setFont(defFont); + Insets insets = new Insets(padding, padding, padding, padding); + JPanel labelPanel = new JPanel(); + labelPanel.add(label); + SwingUtil.addComponent(this, gbl, label, 0, 0, 1, 1, 1.0, 1.0, + GridBagConstraints.CENTER, GridBagConstraints.NONE, + insets); + addMouseListener(new MouseListener() { + @Override + public void mouseReleased(MouseEvent arg0) {} + @Override + public void mousePressed(MouseEvent arg0) {} + @Override + public void mouseExited(MouseEvent arg0) { + DateView.this.setSelect(false); + } + @Override + public void mouseEntered(MouseEvent arg0) { + DateView.this.setSelect(true); + } + @Override + public void mouseClicked(MouseEvent arg0) { + DateView.this.setSelect(false); + performAction(); + } + }); + + } + + private DateView(String labelString){ + this(100); + this.label.setText(labelString); + } + + private DateView(Icon icon){ + this(0); + this.label.setIcon(icon); +// this.label.setBackground(Color.YELLOW); +// this.label.setOpaque(true); + } + + private DateView(DateTime date, + DateTime selectedDate, int month) { + this("" + date.getDayOfMonth()); + this.foreground = date.getMonthOfYear() == month ? foreground + : Color.GRAY; + + GridBagLayout gbl = new GridBagLayout(); + this.setLayout(gbl); + + this.label.setFont(defFont); + + if(date.isEqual(selectedDate)){ + this.defaultBorder = CalendarPanel2.this.greenBorder; + } + + setSelect(false); + + } + + public abstract void performAction(); + + private void setSelect(boolean isSelect) { + if (isSelect) { + this.setBorder(selectBorder); + setBackground(new Color(205, 225, 225)); +// this.label.setForeground(Color.WHITE); + } else { + this.setBorder(this.defaultBorder); + setBackground(this.background); + this.label.setForeground(this.foreground); + } + this.setOpaque(true); + } + } + + private void confirmDate(DateTime date) { + this.textField.setText(convert(date)); + dispose(); + } + + static DateTimeFormatter FMT = DateTimeFormat.forPattern("yyyy-MM-dd"); + + private static String convert(DateTime date) { + return date.toString(FMT); + } + + private static DateTime convert(String string) { + try { + return DateTime.parse(string, FMT); + } catch (IllegalArgumentException e) { + return new DateTime(); + } + } + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/CalendarTimePanel2.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/CalendarTimePanel2.java new file mode 100644 index 0000000..8a17c94 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/CalendarTimePanel2.java @@ -0,0 +1,471 @@ +package com.github.oxygenPlugins.common.gui.types.panels; + + +import java.awt.Color; +import java.awt.Container; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Frame; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Window; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowFocusListener; +import java.io.IOException; +import java.util.Locale; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JDialog; +import javax.swing.JFormattedTextField; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.border.BevelBorder; +import javax.swing.border.Border; + +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; + +import com.github.oxygenPlugins.common.gui.images.IconMap; +import com.github.oxygenPlugins.common.gui.swing.SwingUtil; + + + +public class CalendarTimePanel2 extends JPanel implements MouseListener { + private static final long serialVersionUID = -4261661006435142610L; + private final JDialog dialog; + private final JTextField textField; + + private final Font defFont; + + private final int padding; + private final GridBagLayout gbl = new GridBagLayout(); + + private final int minWidth; + private final int minHeight; + private JPanel contentPanel = new JPanel(); + + private final Border defaultBorder = BorderFactory.createBevelBorder( + BevelBorder.RAISED, new Color(240, 240, 240), new Color(150, 150, + 150)); + private final Border greenBorder = BorderFactory.createBevelBorder( + BevelBorder.LOWERED, new Color(0, 110, 0), new Color(0, 200, + 0)); + private final Border selectBorder = BorderFactory.createBevelBorder( + BevelBorder.RAISED, new Color(30, 20, 120), + new Color(110, 100, 200)); + + public CalendarTimePanel2(JFormattedTextField field, int fontSize, Container owner) { + this(field, fontSize, owner, false); + } + public CalendarTimePanel2(JFormattedTextField field, int fontSize, Container owner, boolean hasTime) { + + if(owner instanceof Dialog){ + dialog = new JDialog((Dialog) owner); + } else if(owner instanceof Frame) { + dialog = new JDialog((Frame) owner); + } else if(owner instanceof Window) { + dialog = new JDialog((Window) owner); + } else { + dialog = new JDialog(new JFrame()); + } + + this.textField = field; + Font defFont = new JLabel().getFont(); + this.defFont = new Font(defFont.getName(), defFont.getStyle(), fontSize); + + this.minWidth = 25 * fontSize; + this.minHeight = this.minWidth + (2 * fontSize); + this.padding = (int) Math.round(fontSize * 0.75); + this.setLayout(gbl); + + String text = this.textField.getText(); + DateTime actuellDat = convert(text); + buildCalendar(actuellDat, actuellDat); + + // this.setBackground(Color.RED); + + dialog.addWindowFocusListener(new WindowFocusListener() { + @Override + public void windowLostFocus(WindowEvent arg0) { + dispose(); + } + + @Override + public void windowGainedFocus(WindowEvent arg0) { + } + }); + dialog.addMouseListener(new MouseListener() { + @Override + public void mouseReleased(MouseEvent arg0) { + } + + @Override + public void mousePressed(MouseEvent arg0) { + } + + @Override + public void mouseExited(MouseEvent arg0) { + } + + @Override + public void mouseEntered(MouseEvent arg0) { + } + + @Override + public void mouseClicked(MouseEvent arg0) { + dispose(); + } + }); + dialog.setMinimumSize(new Dimension(minWidth, minHeight)); + dialog.setUndecorated(true); + dialog.add(this); + } + + private void dispose() { + this.dialog.dispose(); + this.textField.setEnabled(true); + } + + @Override + public void mouseClicked(MouseEvent e) { + if (textField.isEnabled()) { + + String text = this.textField.getText(); + DateTime actuellDat = convert(text); + buildCalendar(actuellDat, actuellDat); + +// dialog.setSize(textField.getWidth(), textField.getWidth()); + dialog.setLocation(getDialogBounds()); + // System.out.println(tfLoc.y); + dialog.setModal(false); + dialog.setVisible(true); +// dialog.pack(); + textField.setEnabled(false); + } else { + dispose(); + } + } + + private Point getDialogBounds(){ + + Point tfLoc = textField.getLocationOnScreen(); + Dimension screen = java.awt.Toolkit.getDefaultToolkit().getScreenSize(); + + int x = tfLoc.x + textField.getWidth() - dialog.getWidth(); + x = x < 0 ? 0 : x; + + int y = tfLoc.y + textField.getHeight(); + y = y < 0 ? 0 : y; + + if((x + dialog.getWidth() ) > screen.width){ + x = screen.width - dialog.getWidth(); + } + if((y + dialog.getHeight()) > screen.height){ + y = tfLoc.y - dialog.getHeight(); + } + + return new Point(x, y); + } + + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + } + + @Override + public void mousePressed(MouseEvent e) { + } + + @Override + public void mouseReleased(MouseEvent e) { + } + + private void clear() { + this.remove(contentPanel); + } + + private void buildCalendar(final DateTime actuell, + final DateTime selectedDate) { + clear(); + this.setBorder(defaultBorder); + contentPanel = new JPanel(); + contentPanel.setLayout(gbl); + contentPanel.setBackground(Color.WHITE); + contentPanel.setOpaque(true); + GridBagLayout gblRoot = new GridBagLayout(); + this.setLayout(gblRoot); + SwingUtil.addComponent(this, gblRoot, contentPanel, 0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHEAST, GridBagConstraints.BOTH); + + JPanel head = buildHeader(actuell, selectedDate); + SwingUtil.addComponent(contentPanel, gbl, head, 0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHEAST, GridBagConstraints.BOTH); + + + JPanel body = new JPanel(); + GridBagLayout gblBody = new GridBagLayout(); + body.setLayout(gblBody); + body.setOpaque(false); + SwingUtil.addComponent(contentPanel, gbl, body, 0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHEAST, GridBagConstraints.BOTH); + + final int month = actuell.getMonthOfYear(); + DateTime monthStart = actuell.minusDays(actuell.getDayOfMonth() - 1); + DateTime nextMonth = actuell.plusMonths(1); + DateTime monthEnd = nextMonth.minusDays(nextMonth.getDayOfMonth()); + + int weeks = monthEnd.getWeekOfWeekyear() - monthStart.getWeekOfWeekyear() + 1; + + DateTime start = monthStart.minusDays(monthStart.getDayOfWeek() - 1); + DateTime end = monthEnd.plusDays(7 - monthEnd.getDayOfWeek()); + + weeks = weeks < 0 ? monthEnd.minusDays(monthEnd.getDayOfWeek()).getWeekOfWeekyear() - monthStart.getWeekOfWeekyear() + 2 : weeks; + if (weeks < 0) { + } else if (weeks < 5){ + end = end.plusWeeks(1); + start = start.minusWeeks(1); + } else if(weeks < 6) { + if (monthStart.getDayOfWeek() - 1 > 7 - monthEnd.getDayOfWeek()){ + end = end.plusWeeks(1); + } else { + start = start.minusWeeks(1); + } + } + + + for (int i = 0; i < 7; i++) { + String labelString = start.plusDays(i).toString( + DateTimeFormat.forPattern("E").withLocale(Locale.ENGLISH)); + JLabel weekLabel = new JLabel(labelString.substring(0, 1)); + weekLabel.setFont(defFont); + SwingUtil.addComponent(body, gblBody, weekLabel, i, 0, 1, 1, + 0.0, 0.0, GridBagConstraints.CENTER, + GridBagConstraints.NONE, new Insets(padding, padding, padding, padding)); + } + + int y = 1; + for (DateTime date = start; date.isBefore(end.plusDays(1)); date = date + .plusDays(1)) { + final DateTime finalDate = date; + final DateView label = new DateView(date, selectedDate, month){ + private static final long serialVersionUID = 1L; + @Override + public void performAction() { + confirmDate(finalDate); + } + }; + + SwingUtil.addComponent(body, gblBody, label, + (date.getDayOfWeek() - 1), y, 1, 1, 1.0, 1.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH); + if (date.dayOfWeek().get() == 7) + y++; + } + this.contentPanel.repaint(); + this.repaint(); + this.updateUI(); + } + +// +// H E A D E R +// + private JPanel buildHeader(final DateTime actuell, final DateTime selectedDate){ + JPanel head = new JPanel(); + GridBagLayout gblHead = new GridBagLayout(); + head.setLayout(gblHead); + head.setOpaque(false); + + IconMap icons = null;; + try { + icons = new IconMap(); + } catch (IOException e) { + } + + DateView yearMinus = new DateView(icons.getIcon(10, 13, true)) { + private static final long serialVersionUID = 1L; + + @Override + public void performAction() { + buildCalendar(actuell.minusYears(1), selectedDate); + } + }; + SwingUtil.addComponent(head, gblHead, yearMinus, 0, 0, 1, 1, 0.0, + 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE); + + DateView yearPlus = new DateView(icons.getIcon(8, 13, true)) { + private static final long serialVersionUID = 1L; + + @Override + public void performAction() { + buildCalendar(actuell.plusYears(1), selectedDate); + } + }; + SwingUtil.addComponent(head, gblHead, yearPlus, 2, 0, 1, 1, 0.0, + 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE); + + JLabel yearLabel = new JLabel(actuell.toString(DateTimeFormat + .forPattern("yyyy"))); + yearLabel.setFont(defFont); + yearLabel.setHorizontalAlignment(JLabel.CENTER); + SwingUtil.addComponent(head, gblHead, yearLabel, 1, 0, 1, 1, 1.0, + 1.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL); + + + + DateView monthMinus = new DateView(icons.getIcon(2, 13, true)) { + private static final long serialVersionUID = 1L; + + @Override + public void performAction() { + buildCalendar(actuell.minusMonths(1), selectedDate); + } + }; + SwingUtil.addComponent(head, gblHead, monthMinus, 0, 1, 1, 1, 0.0, + 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE); + + DateView monthPlus = new DateView(icons.getIcon(0, 13, true)) { + private static final long serialVersionUID = 1L; + + @Override + public void performAction() { + buildCalendar(actuell.plusMonths(1), selectedDate); + } + }; + SwingUtil.addComponent(head, gblHead, monthPlus, 2, 1, 1, 1, 0.0, + 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE); + + JLabel monthLabel = new JLabel(actuell.toString(DateTimeFormat + .forPattern("MMMM").withLocale(Locale.ENGLISH))); + monthLabel.setFont(defFont); + monthLabel.setHorizontalAlignment(JLabel.CENTER); + monthLabel.setBackground(Color.WHITE); + monthLabel.setOpaque(true); + SwingUtil.addComponent(head, gblHead, monthLabel, 1, 1, 1, 1, 1.0, + 1.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL); + + + + return head; + } + + private abstract class DateView extends JPanel { + private static final long serialVersionUID = 1L; + private final JLabel label; + private Color foreground; + private Color background = Color.WHITE; + private Border defaultBorder = CalendarTimePanel2.this.defaultBorder; + + private DateView(int padding){ + this.label = new JLabel(); + this.foreground = Color.BLACK; + this.label.setAlignmentX(JLabel.CENTER_ALIGNMENT); + this.label.setAlignmentY(JLabel.CENTER_ALIGNMENT); + + DateView.this.setSelect(false); + + this.label.setFont(defFont); + Insets insets = new Insets(padding, padding, padding, padding); + JPanel labelPanel = new JPanel(); + labelPanel.add(label); + SwingUtil.addComponent(this, gbl, label, 0, 0, 1, 1, 1.0, 1.0, + GridBagConstraints.CENTER, GridBagConstraints.NONE, + insets); + addMouseListener(new MouseListener() { + @Override + public void mouseReleased(MouseEvent arg0) {} + @Override + public void mousePressed(MouseEvent arg0) {} + @Override + public void mouseExited(MouseEvent arg0) { + DateView.this.setSelect(false); + } + @Override + public void mouseEntered(MouseEvent arg0) { + DateView.this.setSelect(true); + } + @Override + public void mouseClicked(MouseEvent arg0) { + DateView.this.setSelect(false); + performAction(); + } + }); + + } + + private DateView(String labelString){ + this(100); + this.label.setText(labelString); + } + + private DateView(Icon icon){ + this(0); + this.label.setIcon(icon); +// this.label.setBackground(Color.YELLOW); +// this.label.setOpaque(true); + } + + private DateView(DateTime date, + DateTime selectedDate, int month) { + this("" + date.getDayOfMonth()); + this.foreground = date.getMonthOfYear() == month ? foreground + : Color.GRAY; + + GridBagLayout gbl = new GridBagLayout(); + this.setLayout(gbl); + + this.label.setFont(defFont); + + if(date.isEqual(selectedDate)){ + this.defaultBorder = CalendarTimePanel2.this.greenBorder; + } + + setSelect(false); + + } + + public abstract void performAction(); + + private void setSelect(boolean isSelect) { + if (isSelect) { + this.setBorder(selectBorder); + setBackground(new Color(205, 225, 225)); +// this.label.setForeground(Color.WHITE); + } else { + this.setBorder(this.defaultBorder); + setBackground(this.background); + this.label.setForeground(this.foreground); + } + this.setOpaque(true); + } + } + + private void confirmDate(DateTime date) { + this.textField.setText(convert(date)); + dispose(); + } + + static DateTimeFormatter FMT = DateTimeFormat.forPattern("yyyy-MM-dd"); + + private static String convert(DateTime date) { + return date.toString(FMT); + } + + private static DateTime convert(String string) { + try { + return DateTime.parse(string, FMT); + } catch (IllegalArgumentException e) { + return new DateTime(); + } + } + +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/ColorPanel.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/ColorPanel.java new file mode 100644 index 0000000..b0cb5e9 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/ColorPanel.java @@ -0,0 +1,207 @@ +package com.github.oxygenPlugins.common.gui.types.panels; + +import java.awt.Color; +import java.awt.Container; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Window; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowFocusListener; + +import javax.swing.BorderFactory; +import javax.swing.JDialog; +import javax.swing.JFormattedTextField; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSlider; +import javax.swing.JTextField; +import javax.swing.border.BevelBorder; +import javax.swing.border.Border; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import com.github.oxygenPlugins.common.gui.swing.SwingUtil; + + + +public class ColorPanel extends JPanel implements MouseListener{ + private static final long serialVersionUID = 2661956887580911488L; + private final GridBagLayout gbl; + private final int minWidth = 150; + private final int minHeight = 100; + private JDialog dialog; + private final Border outlineBorder = BorderFactory.createBevelBorder( + BevelBorder.LOWERED, new Color(110, 110, 110), new Color(200, 200, + 200)); + private JFormattedTextField textField; + private JLabel rgbCode = new JLabel(); + private JSlider[] sliders = new JSlider[3]; + private Color color; + private final Container owner; + public ColorPanel(JFormattedTextField field, Container owner){ + this(field, field.getBackground(), owner); + } + public ColorPanel(final JFormattedTextField field, Color c, Container owner) { + this.textField = field; + this.owner = owner; + textField.setHorizontalAlignment(JTextField.CENTER); + color = c; + setBorder(outlineBorder); + setBackground(Color.WHITE); + gbl = new GridBagLayout(); + this.setLayout(gbl); + + for (int i = 0; i < sliders.length; i++) { + JPanel colorBar = getColorBar(i); + colorBar.setBackground(Color.WHITE); + SwingUtil.addComponent(this, gbl, colorBar, + 0, i, 1, 1, 1.0, 1.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3)); + } + MouseListener ml = new MouseListener() { + @Override + public void mouseReleased(MouseEvent arg0) {} + @Override + public void mousePressed(MouseEvent arg0) {} + @Override + public void mouseExited(MouseEvent arg0) {} + @Override + public void mouseEntered(MouseEvent arg0) {} + @Override + public void mouseClicked(MouseEvent arg0) { + dialog.dispose(); + } + }; + addMouseListener(ml); +// SwingUtil.addComponent(this, gbl, rgbCode, +// 3, 1, 1, 1, 1.0, 0.0, +// GridBagConstraints.NORTH, GridBagConstraints.BOTH, new Insets(3, 5, 5, 5)); + rgbCode.setSize(rgbCode.getWidth(), textField.getWidth() / 3); + setColor(); + } + private JPanel getColorBar(int i) { + JPanel jp = new JPanel(); + GridBagLayout gbl = new GridBagLayout(); + jp.setLayout(gbl); + + JLabel label = new JLabel(i==0 ? "R" : i==1 ? "G" : "B"); + JLabel maxVal = new JLabel("255"); + JLabel minVal = new JLabel("0"); + sliders[i] = new JSlider(JSlider.HORIZONTAL); + sliders[i].setMinimum(0); + sliders[i].setMaximum(255); + sliders[i].setBackground(i==0 ? Color.RED : i==1 ? Color.GREEN : Color.BLUE); + sliders[i].setPaintTicks(true); + sliders[i].setPaintTrack(true); + sliders[i].setOpaque(false); + sliders[i].setValue(i==0 ? color.getRed() : i==1 ? color.getGreen() : color.getBlue()); + sliders[i].addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent arg0) { + setColor(); + } + }); + SwingUtil.addComponent(jp, gbl, label, + 0, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.WEST, GridBagConstraints.VERTICAL, new Insets(5, 5, 5, 5)); + SwingUtil.addComponent(jp, gbl, minVal, + 1, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5)); + SwingUtil.addComponent(jp, gbl, sliders[i], + 2, 0, 1, 1, 1.0, 0.0, + GridBagConstraints.NORTH, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5)); + SwingUtil.addComponent(jp, gbl, maxVal, + 3, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5)); + return jp; + } + protected void setColor() { + int r = sliders[0].getValue(); + int g = sliders[1].getValue(); + int b = sliders[2].getValue(); + color = new Color(r,g,b); + + textField.setBackground(color); + if(color.getRed()+ color.getGreen() * 1.5 < 334) + textField.setForeground(Color.WHITE); + else + textField.setForeground(Color.BLACK); + textField.setText(Integer.toHexString(color.getRGB()).substring(2)); + } + private void getColor() { + color = textField.getBackground(); + sliders[0].setValue(color.getRed()); + sliders[1].setValue(color.getGreen()); + sliders[2].setValue(color.getBlue()); + } + @Override + public void mouseClicked(MouseEvent e) { + // TODO Auto-generated method stub + + } + @Override + public void mouseEntered(MouseEvent e) { + // TODO Auto-generated method stub + + } + @Override + public void mouseExited(MouseEvent e) { + // TODO Auto-generated method stub + + } + @Override + public void mousePressed(MouseEvent e) { + if (textField.isEnabled()) { + this.getColor(); + if (dialog != null) + dialog.dispose(); + if(owner instanceof Dialog){ + dialog = new JDialog((Dialog) owner); + } else if(owner instanceof Frame) { + dialog = new JDialog((Frame) owner); + } else if(owner instanceof Window) { + dialog = new JDialog((Window) owner); + } else { + dialog = new JDialog(new JFrame()); + } + dialog.addWindowFocusListener(new WindowFocusListener() { + + @Override + public void windowLostFocus(WindowEvent arg0) { + dialog.dispose(); + } + + @Override + public void windowGainedFocus(WindowEvent arg0) { + } + }); + dialog.setUndecorated(true); + dialog.setMinimumSize(new Dimension(minWidth, minHeight)); + Point tfLoc = textField.getLocationOnScreen(); + dialog.setSize(textField.getWidth(), textField.getWidth()); + dialog.setLocation(new Point(tfLoc.x + textField.getWidth() + - dialog.getWidth(), tfLoc.y + textField.getHeight())); + dialog.add(this); + dialog.setModal(false); + dialog.setVisible(true); + } + } +// private Frame getFrame(Component c) { +// if (c instanceof Frame) +// return (Frame) c; +// return getFrame(c.getParent()); +// } + @Override + public void mouseReleased(MouseEvent e) { + // TODO Auto-generated method stub + + } +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/FocusTraversalField.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/FocusTraversalField.java new file mode 100644 index 0000000..26656cd --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/FocusTraversalField.java @@ -0,0 +1,64 @@ +package com.github.oxygenPlugins.common.gui.types.panels; + +import java.awt.event.FocusListener; + +import javax.swing.JComponent; +import javax.swing.JFormattedTextField; + +public class FocusTraversalField extends JFormattedTextField { + + private static final long serialVersionUID = 1L; + private JComponent nextComponent = null; + private JComponent prevComponent = null; + private JComponent parentComponent; + + public FocusTraversalField(){} + + public FocusTraversalField(JComponent prevComponent, JComponent nextComponent){ + this.prevComponent = prevComponent; + this.nextComponent = nextComponent; + + + } + + public void nextFocus(){ + if(nextComponent != null){ + nextComponent.setEnabled(true); + nextComponent.requestFocus(); + } + } + + public void setNextComponent(JComponent nextComp) { + this.nextComponent = nextComp; + } + + public void prevFocus(){ + if(prevComponent != null){ + prevComponent.setEnabled(true); + prevComponent.requestFocus(); + } + } + + public void setPrevComponent(JComponent prevComp) { + this.prevComponent = prevComp; + } + + public void parentFocus(){ + if(parentComponent != null){ + parentComponent.setEnabled(true); + parentComponent.requestFocus(); + } + } + + public void setParentComponent(JComponent parentComp) { + this.parentComponent = parentComp; + } + + public void removeAllFocusListener(){ + + FocusListener[] listeners = this.getFocusListeners(); + for (FocusListener listener : listeners) { + this.removeFocusListener(listener); + } + } +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/MultiChoicePanel.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/MultiChoicePanel.java new file mode 100644 index 0000000..a130825 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/MultiChoicePanel.java @@ -0,0 +1,419 @@ +package com.github.oxygenPlugins.common.gui.types.panels; + + +import java.awt.Color; +import java.awt.Container; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowFocusListener; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JFormattedTextField; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.border.BevelBorder; +import javax.swing.border.Border; + +import com.github.oxygenPlugins.common.gui.images.IconMap; +import com.github.oxygenPlugins.common.gui.swing.SwingUtil; + +// +public class MultiChoicePanel extends JPanel implements MouseListener, FocusListener { + private static final long serialVersionUID = 2661956887580911488L; + private final GridBagLayout gbl; + + private final int minWidth = 100; + private final int minHeight = 0; + + private final int maxHeight = 30; + private final int maxWidth = 0; + + private JDialog dialog; +// private final Border defaultBorder = BorderFactory.createBevelBorder( +// BevelBorder.RAISED, new Color(240, 240, 240), new Color(150, 150, +// 150)); + private final Border outlineBorder = BorderFactory.createBevelBorder( + BevelBorder.LOWERED, new Color(110, 110, 110), new Color(200, 200, + 200)); +// private final Border selectBorder = BorderFactory.createBevelBorder( +// BevelBorder.RAISED, new Color(30, 20, 120), +// new Color(110, 100, 200)); + private JFormattedTextField textField; + + private final ArrayList valueList; + + private int value; + private final int initialValue; + + private JComboBox entryBox; + private final Container owner; + + private final JPanel buttonPanel = new JPanel(); + private final JButton okBtn; + @SuppressWarnings("unused") + private final JButton cancelBtn; + private final JButton clearBtn; + private final boolean hasNull; + + private final String fallbackText; + private final String nullText = "(no value)"; + + private class PanelButton extends JButton{ + private static final long serialVersionUID = 1699184718806511284L; + public PanelButton(Icon i){ + this.setIcon(i); + Dimension dim = new Dimension(i.getIconWidth() + 1, i.getIconHeight() + 1); + this.setMinimumSize(dim); + this.setSize(dim); + } + public PanelButton(String text){ + super(text); + } + } + public MultiChoicePanel(final JFormattedTextField field, Container owner, String[] values) { + this(field, owner, values, false); + } + public MultiChoicePanel(final JFormattedTextField field, Container owner, String[] values, boolean isNullSelectable) { + this.owner = owner; + this.textField = field; + textField.setHorizontalAlignment(JTextField.CENTER); + + this.valueList = new ArrayList(); + this.hasNull = !field.isEnabled(); + + if(isNullSelectable && hasNull){ + valueList.add(nullText); + } + Collections.addAll(this.valueList, values); + + fallbackText = field.getText(); + initialValue = this.valueList.indexOf(fallbackText); + value = initialValue; + +// if(field.isEnabled()){ +// +// } else { +// initialValue = VALUE_NULL; +// value = VALUE_NULL; +// } + setBorder(outlineBorder); + setBackground(Color.WHITE); + gbl = new GridBagLayout(); + this.setLayout(gbl); + + GridBagLayout buttonGbl = new GridBagLayout(); + buttonPanel.setLayout(buttonGbl); + buttonPanel.setVisible(false); + + if(IconMap.ICONS == null){ + try { + IconMap.ICONS = new IconMap(); + } catch (IOException e) { + } + } + + if(IconMap.ICONS != null){ + IconMap icons = IconMap.ICONS; + this.okBtn = new PanelButton(icons.getIcon(2, 10)); + this.clearBtn = new PanelButton(icons.getIcon(10, 11)); + this.cancelBtn = new PanelButton(icons.getIcon(0, 10)); + } else { + this.okBtn = new PanelButton("ok"); + this.clearBtn = new PanelButton("x"); + this.cancelBtn = new PanelButton("c"); + } + + this.okBtn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dispose(); + } + }); + + this.clearBtn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dispose(true); + } + }); + +// this.okBtn.setVisible(false); +// this.clearBtn.setVisible(false); +// this.cancelBtn.setVisible(false); + + + entryBox = new JComboBox(this.valueList.toArray(new String[this.valueList.size()])); + entryBox.setSelectedIndex(value); + KeyListener[] kls = textField.getKeyListeners(); + entryBox.addItemListener(new ItemListener() { + + @Override + public void itemStateChanged(ItemEvent ie) { + if(dialog == null) + return; + if(dialog.isVisible()){ + dispose(); + } + } + }); + + entryBox.addKeyListener(new KeyListener() { + @Override + public void keyTyped(KeyEvent e) {} + @Override + public void keyReleased(KeyEvent e) { + if(e.getKeyChar()=='\n'){ + dispose(); + if (textField instanceof FocusTraversalField) { + FocusTraversalField focusField = (FocusTraversalField) textField; + focusField.nextFocus(); + } + } else if(e.getKeyChar() == KeyEvent.VK_ESCAPE){ + dispose(true); + if (textField instanceof FocusTraversalField) { + FocusTraversalField focusField = (FocusTraversalField) textField; + focusField.parentFocus(); + } + } else if(e.getKeyChar() == KeyEvent.VK_TAB){ + if(textField instanceof FocusTraversalField){ + FocusTraversalField focusField = (FocusTraversalField) textField; + + dispose(); + + if(e.isShiftDown()){ + focusField.prevFocus(); + } else { + focusField.nextFocus(); + } + } + } + } + @Override + public void keyPressed(KeyEvent e) {} + }); + + if(textField instanceof FocusTraversalField){ + textField.setFocusable(true); + entryBox.setFocusTraversalKeysEnabled(false); + ((FocusTraversalField) textField).removeAllFocusListener(); + textField.addFocusListener(this); + } + + SwingUtil.addComponent(this, gbl, entryBox, + 0, 0, 1, 1, 1.0, 1.0, + GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(3, 3, 3, 0)); + + +// SwingUtil.addComponent(this, gbl, okBtn, +// 1, 0, 1, 1, 0.0, 1.0, +// GridBagConstraints.NORTHEAST, GridBagConstraints.VERTICAL, new Insets(3, 0, 0, 3)); + + +// SwingUtil.addComponent(this, gbl, cancelBtn, +// 1, 1, 1, 1, 0.0, 1.0, +// GridBagConstraints.EAST, GridBagConstraints.VERTICAL, new Insets(0, 0, 0, 3)); + + SwingUtil.addComponent(this, gbl, clearBtn, + 1, 0, 1, 1, 0.0, 1.0, + GridBagConstraints.SOUTHEAST, GridBagConstraints.VERTICAL, new Insets(0, 0, 3, 3)); + + + MouseListener ml = new MouseListener() { + @Override + public void mouseReleased(MouseEvent arg0) {} + @Override + public void mousePressed(MouseEvent arg0) {} + @Override + public void mouseExited(MouseEvent arg0) { + +// switchToField(); + } + @Override + public void mouseEntered(MouseEvent arg0) { + +// switchToButtons(); + } + @Override + public void mouseClicked(MouseEvent arg0) { + dispose(); + } + }; + + addMouseListener(ml); + } + + + + protected void setText() { + int value = this.entryBox.getSelectedIndex(); + boolean isNull = isNull(value); + this.textField.setEnabled(!isNull); + this.textField.setText(convert(this.entryBox.getSelectedIndex())); + textField.repaint(); + } + private void getText() { + String text = textField.getText(); + if(textField.isEnabled()){ + value = convert(text); + } else { + value = 0; + text = nullText; + } + entryBox.setSelectedItem(text); + } + + private boolean isNull(int value){ + if(value >= valueList.size()) + return true; + if(entryBox.getItemAt(value) == this.nullText) + return true; + if(value < 0) + return true; + return false; + } + + private String convert(int value){ + if(isNull(value)) + return fallbackText; + return valueList.get(value); + } + private int convert(String valueString){ + int i = 0; + for (String label : valueList) { + if(valueString.equals(label)) + return i; + i++; + } + return 0; + } + + @Override + public void mouseClicked(MouseEvent e) { + // TODO Auto-generated method stub + + } + @Override + public void mouseEntered(MouseEvent e) { + + } + @Override + public void mouseExited(MouseEvent e) { + // TODO Auto-generated method stub + + } + @Override + public void mousePressed(MouseEvent e) { + activate(); + } + @Override + public void mouseReleased(MouseEvent e) { + // TODO Auto-generated method stub + + } + private void activate(){ +// if (textField.isEnabled()) { +// if (dialog != null) { +// dispose(); +// } + this.getText(); + + if(dialog == null){ + if(owner instanceof Dialog){ + dialog = new JDialog((Dialog) owner); + } else if(owner instanceof Frame) { + dialog = new JDialog((Frame) owner); + } else if(owner instanceof Window) { + dialog = new JDialog((Window) owner); + } else { + dialog = new JDialog(new JFrame()); + } + } + dialog.addWindowFocusListener(new WindowFocusListener() { + + @Override + public void windowLostFocus(WindowEvent arg0) { + if(dialog != null) + dispose(); + } + + @Override + public void windowGainedFocus(WindowEvent arg0) { + } + }); + dialog.setUndecorated(true); + dialog.setMinimumSize(new Dimension(minWidth, minHeight)); + Point tfLoc = textField.getLocationOnScreen(); + int finalWidth = textField.getWidth() * 2; + int finalHeight = textField.getHeight() * 2; + + finalHeight = this.maxHeight > 0 && this.maxHeight < finalHeight ? this.maxHeight : finalHeight; + finalWidth = this.maxWidth > 0 && this.maxWidth < finalWidth ? this.maxWidth : finalWidth; + + dialog.setMaximumSize(new Dimension(finalWidth, finalHeight)); + + dialog.setSize(finalWidth, finalHeight); + dialog.setLocation(new Point((int) (tfLoc.x - finalWidth * 0.25), + (int) (tfLoc.y - finalHeight * 0.25))); + dialog.add(this); + dialog.setModal(false); + dialog.setVisible(true); +// } + } + + private void dispose(){ + dispose(false); + } + private void dispose(boolean unsetText){ + if(unsetText){ + if(hasNull){ + this.textField.setEnabled(false); + } else { + this.textField.setEnabled(true); + } + this.textField.setText(convert(initialValue)); + this.textField.repaint(); + } else { + this.setText(); + } + if(dialog != null){ + this.dialog.dispose(); + this.dialog = null; + } + } + + @Override + public void focusGained(FocusEvent arg0) { + if(dialog == null){ +// activate(); + } + } + @Override + public void focusLost(FocusEvent arg0) { +// dispose(); + } +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/StringPanel.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/StringPanel.java new file mode 100644 index 0000000..583f336 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/StringPanel.java @@ -0,0 +1,358 @@ +package com.github.oxygenPlugins.common.gui.types.panels; + + +import java.awt.Color; +import java.awt.Container; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowFocusListener; +import java.io.IOException; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFormattedTextField; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.border.BevelBorder; +import javax.swing.border.Border; + +import com.github.oxygenPlugins.common.gui.images.IconMap; +import com.github.oxygenPlugins.common.gui.swing.SwingUtil; +import com.github.oxygenPlugins.common.gui.types._Verifier; + +// +public class StringPanel extends JPanel implements MouseListener, FocusListener { + private static final long serialVersionUID = 2661956887580911488L; + private final GridBagLayout gbl; + private final int minWidth = 75; + private final int minHeight = 0; + private JDialog dialog; +// private final Border defaultBorder = BorderFactory.createBevelBorder( +// BevelBorder.RAISED, new Color(240, 240, 240), new Color(150, 150, +// 150)); + private final Border outlineBorder = BorderFactory.createBevelBorder( + BevelBorder.LOWERED, new Color(110, 110, 110), new Color(200, 200, + 200)); +// private final Border selectBorder = BorderFactory.createBevelBorder( +// BevelBorder.RAISED, new Color(30, 20, 120), +// new Color(110, 100, 200)); + private JFormattedTextField textField; + + private String value; + private final String initialValue; + + private JFormattedTextField entryField; + private final Container owner; + + private final JPanel buttonPanel = new JPanel(); + private final JButton okBtn; + @SuppressWarnings("unused") + private final JButton cancelBtn; + private final JButton clearBtn; + + private class PanelButton extends JButton{ + private static final long serialVersionUID = 1699184718806511284L; + public PanelButton(Icon i){ + this.setIcon(i); + Dimension dim = new Dimension(i.getIconWidth() + 1, i.getIconHeight() + 1); + this.setMinimumSize(dim); + this.setSize(dim); + } + public PanelButton(String text){ + super(text); + } + } + + public StringPanel(final JFormattedTextField field, _Verifier verifier, Container owner){ + this(field, owner); + verifier.setVerifier(entryField, owner, false); + } + public StringPanel(final JFormattedTextField field, Container owner) { + this.owner = owner; + this.textField = field; + textField.setHorizontalAlignment(JTextField.CENTER); + if(field.isEnabled()){ + initialValue = field.getText(); + value = initialValue; + } else { + initialValue = null; + value = null; + } + setBorder(outlineBorder); + setBackground(Color.WHITE); + gbl = new GridBagLayout(); + this.setLayout(gbl); + + GridBagLayout buttonGbl = new GridBagLayout(); + buttonPanel.setLayout(buttonGbl); + buttonPanel.setVisible(false); + + if(IconMap.ICONS == null){ + try { + IconMap.ICONS = new IconMap(); + } catch (IOException e) { + } + } + + if(IconMap.ICONS != null){ + IconMap icons = IconMap.ICONS; + this.okBtn = new PanelButton(icons.getIcon(2, 10)); + this.clearBtn = new PanelButton(icons.getIcon(10, 11)); + this.cancelBtn = new PanelButton(icons.getIcon(0, 10)); + } else { + this.okBtn = new PanelButton("ok"); + this.clearBtn = new PanelButton("x"); + this.cancelBtn = new PanelButton("c"); + } + + this.okBtn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dispose(); + } + }); + + this.clearBtn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dispose(true); + } + }); + +// this.okBtn.setVisible(false); +// this.clearBtn.setVisible(false); +// this.cancelBtn.setVisible(false); + + + entryField = new JFormattedTextField(); + if(value == null){ + entryField.setText(""); + } else { + entryField.setText(value); + } + KeyListener[] kls = textField.getKeyListeners(); + + for (int i = 0; i < kls.length; i++) { + entryField.addKeyListener(kls[i]); + } + entryField.addKeyListener(new KeyListener() { + @Override + public void keyTyped(KeyEvent e) {} + @Override + public void keyReleased(KeyEvent e) { + if(e.getKeyChar()=='\n'){ + dispose(); + if (textField instanceof FocusTraversalField) { + FocusTraversalField focusField = (FocusTraversalField) textField; + focusField.nextFocus(); + } + } else if(e.getKeyChar() == KeyEvent.VK_ESCAPE){ + dispose(true); + if (textField instanceof FocusTraversalField) { + FocusTraversalField focusField = (FocusTraversalField) textField; + focusField.parentFocus(); + } + } else if(e.getKeyChar() == KeyEvent.VK_TAB){ + if(textField instanceof FocusTraversalField){ + FocusTraversalField focusField = (FocusTraversalField) textField; + + dispose(); + + if(e.isShiftDown()){ + focusField.prevFocus(); + } else { + focusField.nextFocus(); + } + } + } + } + @Override + public void keyPressed(KeyEvent e) {} + }); + + if(textField instanceof FocusTraversalField){ + textField.setFocusable(true); + entryField.setFocusTraversalKeysEnabled(false); + ((FocusTraversalField) textField).removeAllFocusListener(); + textField.addFocusListener(this); + } + + SwingUtil.addComponent(this, gbl, entryField, + 0, 0, 1, 3, 1.0, 1.0, + GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(3, 3, 3, 0)); + + + SwingUtil.addComponent(this, gbl, okBtn, + 1, 0, 1, 1, 0.0, 1.0, + GridBagConstraints.NORTHEAST, GridBagConstraints.VERTICAL, new Insets(3, 0, 0, 3)); + + +// SwingUtil.addComponent(this, gbl, cancelBtn, +// 1, 1, 1, 1, 0.0, 1.0, +// GridBagConstraints.EAST, GridBagConstraints.VERTICAL, new Insets(0, 0, 0, 3)); + + SwingUtil.addComponent(this, gbl, clearBtn, + 1, 1, 1, 1, 0.0, 1.0, + GridBagConstraints.SOUTHEAST, GridBagConstraints.VERTICAL, new Insets(0, 0, 3, 3)); + + + MouseListener ml = new MouseListener() { + @Override + public void mouseReleased(MouseEvent arg0) {} + @Override + public void mousePressed(MouseEvent arg0) {} + @Override + public void mouseExited(MouseEvent arg0) { + +// switchToField(); + } + @Override + public void mouseEntered(MouseEvent arg0) { + +// switchToButtons(); + } + @Override + public void mouseClicked(MouseEvent arg0) { + dispose(); + } + }; + + addMouseListener(ml); + } + + + + + protected void setText() { + this.textField.setEnabled(true); + this.textField.setText(this.entryField.getText()); + textField.repaint(); + } + private void getText() { + if(textField.isEnabled()){ + value = textField.getText(); + } else { + value = ""; + } + entryField.setText(value); + + if(!value.equals("")){ + entryField.setSelectionStart(0); + entryField.setSelectionEnd(value.length()); + } + } + @Override + public void mouseClicked(MouseEvent e) { + // TODO Auto-generated method stub + + } + @Override + public void mouseEntered(MouseEvent e) { + + } + @Override + public void mouseExited(MouseEvent e) { + // TODO Auto-generated method stub + + } + @Override + public void mousePressed(MouseEvent e) { + activate(); + } + @Override + public void mouseReleased(MouseEvent e) { + // TODO Auto-generated method stub + + } + private void activate(){ +// if (textField.isEnabled()) { + this.getText(); +// if (dialog != null) { +// dispose(); +// } + if(dialog == null){ + if(owner instanceof Dialog){ + dialog = new JDialog((Dialog) owner); + } else if(owner instanceof Frame) { + dialog = new JDialog((Frame) owner); + } else if(owner instanceof Window) { + dialog = new JDialog((Window) owner); + } else { + dialog = new JDialog(new JFrame()); + } + } + dialog.addWindowFocusListener(new WindowFocusListener() { + + @Override + public void windowLostFocus(WindowEvent arg0) { + if(dialog != null) + dispose(); + } + + @Override + public void windowGainedFocus(WindowEvent arg0) { + } + }); + dialog.setUndecorated(true); + dialog.setMinimumSize(new Dimension(minWidth, minHeight)); + Point tfLoc = textField.getLocationOnScreen(); + int finalWidth = textField.getWidth() * 2; + int finalHeight = textField.getHeight() * 2; + dialog.setSize(finalWidth, finalHeight); + dialog.setLocation(new Point((int) (tfLoc.x - finalWidth * 0.25), + (int) (tfLoc.y - finalHeight * 0.25))); + dialog.add(this); + dialog.setModal(false); + dialog.setVisible(true); +// } + } + protected void dispose() { + this.dispose(false); + } + private void dispose(boolean unsetText){ + if(unsetText){ + if(initialValue != null){ + this.textField.setEnabled(true); + } else { + this.textField.setEnabled(false); + } + this.textField.setText(initialValue); + this.textField.repaint(); + } else { + this.setText(); + } + if(dialog != null){ + this.dialog.dispose(); + this.dialog = null; + } + } + + @Override + public void focusGained(FocusEvent arg0) { + if(dialog == null){ +// activate(); + } + } + @Override + public void focusLost(FocusEvent arg0) { +// dispose(); + } +} diff --git a/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/TimePanel.java b/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/TimePanel.java new file mode 100644 index 0000000..f7f50d4 --- /dev/null +++ b/src/main/java/com/github/oxygenPlugins/common/gui/types/panels/TimePanel.java @@ -0,0 +1,557 @@ +package com.github.oxygenPlugins.common.gui.types.panels; + +import java.awt.Color; +import java.awt.Container; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Frame; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Point; +import java.awt.Window; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowFocusListener; +import java.io.IOException; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JDialog; +import javax.swing.JFormattedTextField; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.border.BevelBorder; +import javax.swing.border.Border; + +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; + +import com.github.oxygenPlugins.common.gui.images.IconMap; +import com.github.oxygenPlugins.common.gui.swing.SwingUtil; +import com.github.oxygenPlugins.common.gui.types.IntegerAreaVerifier; + + + +public class TimePanel extends JPanel implements MouseListener { + private static final long serialVersionUID = -4261661006435142610L; + private final JDialog dialog; + private final JTextField textField; + + private final Font defFont; + + @SuppressWarnings("unused") + private final int padding; + private final GridBagLayout gbl = new GridBagLayout(); + + // private final int minWidth; + // private final int minHeight; + private JPanel contentPanel = new JPanel(); + + JFormattedTextField hour = new JFormattedTextField(); + JFormattedTextField minutes = new JFormattedTextField(); + JFormattedTextField sec = new JFormattedTextField(); + + private final Border defaultBorder = BorderFactory.createBevelBorder( + BevelBorder.RAISED, new Color(240, 240, 240), new Color(150, 150, + 150)); + private final Border greenBorder = BorderFactory.createBevelBorder( + BevelBorder.LOWERED, new Color(0, 110, 0), new Color(0, 200, 0)); + private final Border selectBorder = BorderFactory.createBevelBorder( + BevelBorder.RAISED, new Color(30, 20, 120), + new Color(110, 100, 200)); + private String initialValue; + + public TimePanel(JFormattedTextField field, int fontSize, Container owner) { + + if(field.isEnabled()){ + initialValue = field.getText(); + setTime(convert(initialValue)); + } else { + initialValue = null; + } + + if (owner instanceof Dialog) { + dialog = new JDialog((Dialog) owner); + } else if (owner instanceof Frame) { + dialog = new JDialog((Frame) owner); + } else if (owner instanceof Window) { + dialog = new JDialog((Window) owner); + } else { + dialog = new JDialog(new JFrame()); + } + this.setLayout(gbl); + this.textField = field; + Font defFont = new JLabel().getFont(); + this.defFont = new Font(defFont.getName(), defFont.getStyle(), fontSize); + + // this.minWidth = 25 * fontSize; + // this.minHeight = 25 * fontSize; + this.padding = (int) Math.round(fontSize * 0.1); + this.setLayout(gbl); + + String text = this.textField.getText(); + DateTime actuellDat = convert(text); + buildCalendar(actuellDat, actuellDat); + Dimension minDim = new Dimension(fontSize * 7 / 4, fontSize * 2); + hour.setMinimumSize(minDim); + hour.setPreferredSize(minDim); + minutes.setMinimumSize(minDim); + minutes.setPreferredSize(minDim); + sec.setMinimumSize(minDim); + sec.setPreferredSize(minDim); + + + dialog.addWindowFocusListener(new WindowFocusListener() { + @Override + public void windowLostFocus(WindowEvent arg0) { + dispose(); + } + + @Override + public void windowGainedFocus(WindowEvent arg0) { + } + }); + dialog.addMouseListener(new MouseListener() { + @Override + public void mouseReleased(MouseEvent arg0) { + } + + @Override + public void mousePressed(MouseEvent arg0) { + } + + @Override + public void mouseExited(MouseEvent arg0) { + } + + @Override + public void mouseEntered(MouseEvent arg0) { + } + + @Override + public void mouseClicked(MouseEvent arg0) { + dispose(); + } + }); + // dialog.setMinimumSize(new Dimension(minWidth, minHeight)); + dialog.setUndecorated(true); + dialog.add(this); + } + + private void dispose() { + this.dialog.dispose(); + this.textField.setEnabled(true); + } + + @Override + public void mouseClicked(MouseEvent e) { + if (textField.isEnabled()) { + + String text = this.textField.getText(); + DateTime actuellDat = convert(text); + buildCalendar(actuellDat, actuellDat); + + // dialog.setSize(textField.getWidth(), textField.getWidth()); + int finalWidth = textField.getWidth() * 2; + int finalHeight = textField.getHeight() * 2; + dialog.setSize(finalWidth, finalHeight); + + dialog.pack(); + + dialog.setLocation(getDialogBounds()); + // System.out.println(tfLoc.y); + dialog.setModal(false); + dialog.setVisible(true); + textField.setEnabled(false); + } else { + dispose(); + } + } + + private Point getDialogBounds() { + + Point tfLoc = textField.getLocationOnScreen(); + + return new Point((int) (tfLoc.x - dialog.getWidth() * 0.25), + (int) (tfLoc.y - dialog.getHeight() * 0.25)); + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + } + + @Override + public void mousePressed(MouseEvent e) { + } + + @Override + public void mouseReleased(MouseEvent e) { + } + + private void clear() { + this.remove(contentPanel); + } + + private void buildCalendar(final DateTime actuell, + final DateTime selectedDate) { + clear(); + + IconMap icons = null; + ; + try { + icons = new IconMap(); + } catch (IOException e) { + } + GridBagLayout gblContent = new GridBagLayout(); + + this.setBorder(defaultBorder); + contentPanel = new JPanel(); + contentPanel.setLayout(gblContent); + contentPanel.setBackground(Color.WHITE); + contentPanel.setOpaque(true); + + SwingUtil.addComponent(this, gbl, contentPanel, 0, 0, 1, 1, 1.0, 1.0, + GridBagConstraints.NORTHEAST, GridBagConstraints.BOTH); + + // JPanel head = buildHeader(actuell, selectedDate); + // SwingUtil.addComponent(contentPanel, gbl, head, 0, 0, 1, 1, 0.0, 0.0, + // GridBagConstraints.NORTHEAST, GridBagConstraints.BOTH); + + IntegerAreaVerifier iavHour = new IntegerAreaVerifier(0, 23); + IntegerAreaVerifier iavMinutes = new IntegerAreaVerifier(0, 59); + IntegerAreaVerifier iavSec = new IntegerAreaVerifier(0, 59); + + iavHour.setVerifier(hour, dialog, false); + + iavMinutes.setVerifier(minutes, dialog, false); + + iavSec.setVerifier(sec, dialog, false); + + setTime(actuell); +// int tinySize = 25; +// JButton hourP = new PanelButton(icons.getIcon(6, 13)); +// hourP.addActionListener(new ActionListener() { +// @Override +// public void actionPerformed(ActionEvent arg0) { +// setTime(getTime().plusHours(1)); +// } +// }); +// JButton hourM = new PanelButton(icons.getIcon(4, 13)); +// hourM.addActionListener(new ActionListener() { +// @Override +// public void actionPerformed(ActionEvent arg0) { +// setTime(getTime().minusHours(1)); +// } +// }); +// JButton minP = new PanelButton(icons.getIcon(6, 13)); +// hourM.addActionListener(new ActionListener() { +// @Override +// public void actionPerformed(ActionEvent arg0) { +// setTime(getTime().plusMinutes(1)); +// } +// }); +// JButton minM = new PanelButton(icons.getIcon(4, 13)); +// hourM.addActionListener(new ActionListener() { +// @Override +// public void actionPerformed(ActionEvent arg0) { +// setTime(getTime().minusMinutes(1)); +// } +// }); +// JButton secP = new PanelButton(icons.getIcon(6, 13)); +// hourM.addActionListener(new ActionListener() { +// @Override +// public void actionPerformed(ActionEvent arg0) { +// setTime(getTime().plusSeconds(1)); +// } +// }); +// JButton secM = new PanelButton(icons.getIcon(4, 13)); +// hourM.addActionListener(new ActionListener() { +// @Override +// public void actionPerformed(ActionEvent arg0) { +// setTime(getTime().minusSeconds(1)); +// } +// }); +// JButton conformBtn = new PanelButton(icons.getIcon(2, 10)); +// hourM.addActionListener(new ActionListener() { +// @Override +// public void actionPerformed(ActionEvent arg0) { +// confirmDate(getTime()); +// } +// }); + + + DateView hourP = new DateView(icons.getIcon(6, 13)) { + /** + * + */ + private static final long serialVersionUID = 1L; + + @Override + public void performAction() { + setTime(getTime().plusHours(1)); + } + }; + + DateView hourM = new DateView(icons.getIcon(4, 13)) { + private static final long serialVersionUID = 1L; + + @Override + public void performAction() { + setTime(getTime().minusHours(1)); + } + }; + DateView minP = new DateView(icons.getIcon(6, 13)) { + private static final long serialVersionUID = 1L; + + @Override + public void performAction() { + setTime(getTime().plusMinutes(1)); + } + }; + DateView minM = new DateView(icons.getIcon(4, 13)) { + private static final long serialVersionUID = 1L; + + @Override + public void performAction() { + setTime(getTime().minusMinutes(1)); + } + }; + DateView secP = new DateView(icons.getIcon(6, 13)) { + private static final long serialVersionUID = 1L; + + @Override + public void performAction() { + setTime(getTime().plusSeconds(1)); + } + }; + DateView secM = new DateView(icons.getIcon(4, 13)) { + private static final long serialVersionUID = 1L; + + @Override + public void performAction() { + setTime(getTime().minusSeconds(1)); + } + }; + DateView conformBtn = new DateView(icons.getIcon(2, 10)) { + private static final long serialVersionUID = 1L; + + @Override + public void performAction() { + confirmDate(getTime()); + } + }; + DateView clearBtn = new DateView(icons.getIcon(10, 11)) { + private static final long serialVersionUID = 1L; + + @Override + public void performAction() { + unsetTextAndDispose(); + } + }; + + SwingUtil.addComponent(contentPanel, gblContent, hour, 0, 0, 1, 2, 0.0, + 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH); + SwingUtil + .addComponent(contentPanel, gblContent, hourP, 1, 0, 1, 1, 0.0, + 0.0, GridBagConstraints.NORTHWEST, + GridBagConstraints.NONE); + SwingUtil + .addComponent(contentPanel, gblContent, hourM, 1, 1, 1, 1, 0.0, + 0.0, GridBagConstraints.SOUTHWEST, + GridBagConstraints.NONE); + SwingUtil.addComponent(contentPanel, gblContent, minutes, 2, 0, 1, 2, + 0.0, 1.0, GridBagConstraints.NORTH, GridBagConstraints.BOTH); + SwingUtil.addComponent(contentPanel, gblContent, minP, 3, 0, 1, 1, 0.0, + 0.0, GridBagConstraints.NORTH, GridBagConstraints.NONE); + SwingUtil.addComponent(contentPanel, gblContent, minM, 3, 1, 1, 1, 0.0, + 0.0, GridBagConstraints.SOUTH, GridBagConstraints.NONE); + SwingUtil.addComponent(contentPanel, gblContent, sec, 4, 0, 1, 2, 0.0, + 1.0, GridBagConstraints.NORTHEAST, GridBagConstraints.BOTH); + SwingUtil.addComponent(contentPanel, gblContent, secP, 5, 0, 1, 1, 0.0, + 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE); + SwingUtil.addComponent(contentPanel, gblContent, secM, 5, 1, 1, 1, 0.0, + 0.0, GridBagConstraints.SOUTHWEST, GridBagConstraints.NONE); + + SwingUtil.addComponent(contentPanel, gblContent, conformBtn, 6, 0, 1, + 1, 0.0, 0.0, GridBagConstraints.SOUTHWEST, + GridBagConstraints.NONE); + SwingUtil.addComponent(contentPanel, gblContent, clearBtn, 6, 1, 1, + 1, 0.0, 0.0, GridBagConstraints.SOUTHWEST, + GridBagConstraints.NONE); + + this.contentPanel.repaint(); + this.repaint(); + this.updateUI(); + } + + protected void unsetTextAndDispose() { + if(initialValue != null){ + this.textField.setEnabled(true); + } else { + this.textField.setEnabled(false); + } + this.textField.setText(initialValue); + this.textField.repaint(); + + this.dialog.dispose(); + } + + private DateTime getTime() { + String timeString = "T" + hour.getText() + ":" + minutes.getText() + + ":" + sec.getText(); + DateTime time = DateTime.parse(timeString); + return time; + } + + + private void setTime(DateTime time) { + setIntToField(hour, time.getHourOfDay()); + setIntToField(minutes, time.getMinuteOfHour()); + setIntToField(sec, time.getSecondOfMinute()); + } + + private void setIntToField(JFormattedTextField field, int value) { + String valueString = "" + value; + if (valueString.length() == 1) { + valueString = "0" + valueString; + } + field.setText(valueString); + } + + + private abstract class DateView extends JLabel { + private static final long serialVersionUID = 1L; + private final JLabel label; + private Color foreground; + private Color background = Color.WHITE; + private Border defaultBorder = TimePanel.this.defaultBorder; + + private DateView(int padding) { + this.label = new JLabel(); + this.foreground = Color.BLACK; +// this.label.setAlignmentX(JLabel.CENTER_ALIGNMENT); +// this.label.setAlignmentY(JLabel.CENTER_ALIGNMENT); + + setSelect(false); +// this.setBackground(Color.RED); +// this.label.setBackground(Color.BLUE); +// this.label.setOpaque(true); + + this.setFont(defFont); +// Insets insets = new Insets(padding, padding, padding, padding); +// SwingUtil.addComponent(this, gbl, label, 0, 0, 1, 1, 1.0, 1.0, +// GridBagConstraints.CENTER, GridBagConstraints.NONE, insets); + addMouseListener(new MouseListener() { + @Override + public void mouseReleased(MouseEvent arg0) { + } + + @Override + public void mousePressed(MouseEvent arg0) { + } + + @Override + public void mouseExited(MouseEvent arg0) { + DateView.this.setSelect(false); + } + + @Override + public void mouseEntered(MouseEvent arg0) { + DateView.this.setSelect(true); + } + + @Override + public void mouseClicked(MouseEvent arg0) { +// DateView.this.setSelect(false); + performAction(); + } + }); + + } + + private DateView(String labelString) { + this(100); + this.label.setText(labelString); + } + + private DateView(Icon icon) { + this(0); + this.setIcon(icon); + Dimension dim = new Dimension(icon.getIconWidth() + 1, icon.getIconHeight() + 1); + this.setMinimumSize(dim); + this.setSize(dim); + // this.label.setBackground(Color.YELLOW); + // this.label.setOpaque(true); + } + + private DateView(Icon icon, int size) { + this(icon); + Dimension dim = new Dimension(size, size); + this.setMaximumSize(dim); + setSize(dim); + setPreferredSize(dim); + } + + private DateView(DateTime date, DateTime selectedDate, int month) { + this("" + date.getDayOfMonth()); + this.foreground = date.getMonthOfYear() == month ? foreground + : Color.GRAY; + + GridBagLayout gbl = new GridBagLayout(); + this.setLayout(gbl); + + this.label.setFont(defFont); + + if (date.isEqual(selectedDate)) { + this.defaultBorder = TimePanel.this.greenBorder; + } + + setSelect(false); + + } + + public abstract void performAction(); + + private void setSelect(boolean isSelect) { + if (isSelect) { + this.setBorder(selectBorder); + setBackground(new Color(205, 225, 225)); + // this.label.setForeground(Color.WHITE); + } else { + this.setBorder(this.defaultBorder); + setBackground(this.background); + this.label.setForeground(this.foreground); + } + this.setOpaque(true); + } + } + + private void confirmDate(DateTime date) { + this.textField.setText(convert(date)); + dispose(); + } + + static DateTimeFormatter FMT = DateTimeFormat.forPattern("HH:mm:ss"); + + private static String convert(DateTime date) { + return date.toString(FMT); + } + + private static DateTime convert(String string) { + try { + return DateTime.parse(string, FMT); + } catch (IllegalArgumentException e) { + return new DateTime(); + } + } + +}