Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Imagepanel improvements #689

Closed
wants to merge 69 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
37cdc31
Fix token ids reset on server start
Merudo Aug 26, 2019
0dba3db
Merge pull request #620 from Merudo/tokenIds
Phergus Aug 27, 2019
1aaa566
Fix cut & paste changes token id
Merudo Aug 26, 2019
a1f4d50
Merge pull request #625 from Merudo/cutTokenIds
Phergus Aug 27, 2019
6b202a0
Fix "paste" option remaining grayed out after Copy/Cut token
Merudo Aug 28, 2019
aa15211
Fix switching from/to the measure tool not updating cursor right away
Merudo Aug 28, 2019
0822f8f
Merge pull request #630 from Merudo/CopyCut
Phergus Aug 28, 2019
1209159
Merge branch 'develop' into fixMeasureCursor
Phergus Aug 28, 2019
963faf3
Merge pull request #632 from Merudo/fixMeasureCursor
Phergus Aug 28, 2019
5729052
Fix bug created by dragging token from library to map
Merudo Aug 28, 2019
453e94c
Merge pull request #633 from Merudo/dragTokenToMap
Phergus Aug 28, 2019
cef98d8
Fix incorrect message for assert() when the second parameter is number
Merudo Aug 31, 2019
454d004
Translate a few UI elements in french
Merudo Aug 31, 2019
2de64f7
Consolidate utility methods for macro functions in FunctionUtil
Merudo Sep 1, 2019
41d4b46
Merge pull request #639 from Merudo/frenchTranslation
Phergus Sep 1, 2019
6dcc9d3
Merge branch 'develop' into assertString
Phergus Sep 1, 2019
97fc48b
Merge pull request #638 from Merudo/assertString
Phergus Sep 1, 2019
4a17fb5
Merge branch 'develop' into FunctionUtil
Phergus Sep 1, 2019
80d0b97
Merge pull request #635 from Merudo/FunctionUtil
Phergus Sep 1, 2019
776413b
Add parameter in FunctionUtil to allow/disallow text to BigDecimal
Merudo Sep 2, 2019
774a4d9
Change ZoomFunction to use FunctionUtil
Merudo Sep 2, 2019
8d51993
Merge pull request #647 from Merudo/FunctionUtil2
Phergus Sep 3, 2019
f81bc0d
Add translation support for "Select Map" button
Merudo Sep 4, 2019
96be505
Merge pull request #652 from Merudo/selectMap
Phergus Sep 4, 2019
073a4cb
Change wrong nb of parameters error messages to display function name
Merudo Sep 6, 2019
d5c2653
Merge pull request #641 from Merudo/parserErrors
Phergus Sep 6, 2019
26be408
Change parser implementation to 1.5.4
Merudo Sep 6, 2019
f2b33b2
Merge pull request #659 from Merudo/parserErrors
Phergus Sep 6, 2019
e9734eb
Add json.path.read function (based on jayway)
Merudo Sep 5, 2019
6300ca4
Add error handling for json.path.read
Merudo Sep 5, 2019
57a09cd
Add json.path.add, json.path.add/put/set, and json.path.delete functions
Merudo Sep 5, 2019
969d2bd
Consolidate methods checkNumberOfParameters and getTokenFromParam
Merudo Sep 2, 2019
827c9f9
Merge pull request #661 from RPTools/master
JamzTheMan Sep 6, 2019
587f7a2
Fix bring to front/send to back need to be done twice
Merudo Sep 6, 2019
e2a43e6
Merge branch 'develop' into FunctionUtil3
JamzTheMan Sep 6, 2019
bafb9c0
Merge pull request #648 from Merudo/FunctionUtil3
JamzTheMan Sep 6, 2019
f8fb540
Merge branch 'develop' into ZOrderBug
JamzTheMan Sep 6, 2019
b811487
Merge pull request #662 from Merudo/ZOrderBug
JamzTheMan Sep 6, 2019
b05eb1b
Merge branch 'develop' into jayway
JamzTheMan Sep 6, 2019
bf81c01
Merge pull request #657 from Merudo/jayway
JamzTheMan Sep 6, 2019
5c940f7
Update build.gradle
JamzTheMan Sep 6, 2019
d46202c
Fix for ConcurrentModificationException
JamzTheMan Sep 7, 2019
edf297d
Spotless applied
JamzTheMan Sep 7, 2019
d280107
Merge pull request #664 from JamzTheMan/develop
JamzTheMan Sep 7, 2019
8d50aaa
Add new Server Option for GM to Reveal FoW for Unowned Tokens
JamzTheMan Sep 7, 2019
1dd7778
Merge branch 'develop' into develop
JamzTheMan Sep 7, 2019
5d2d93c
Merge pull request #666 from JamzTheMan/develop
Phergus Sep 7, 2019
4c614eb
Add playStream, stopStream, and editStream functions to stream audio
Merudo Sep 8, 2019
48b1481
Fix disabling streams, and make stream functions thread-safe
Merudo Sep 8, 2019
185e2db
Merge pull request #668 from Merudo/playStream
Phergus Sep 8, 2019
2016476
Add features to playStream functions
Merudo Sep 9, 2019
c52d853
Merge pull request #669 from Merudo/playStream
Phergus Sep 9, 2019
efc64ac
Fix getStreamProperties wrongly returning "PLAYING" , change ms to secs
Merudo Sep 10, 2019
6502a8e
Merge pull request #671 from Merudo/playStream
Phergus Sep 10, 2019
6520666
Add Volume Slider and Mute Button to Toolbar
Merudo Sep 10, 2019
63034be
Merge pull request #673 from Merudo/volumeSlider
Phergus Sep 10, 2019
5024fa9
Add "fadeout" parameter to stopStream
Merudo Sep 10, 2019
142205f
Merge pull request #674 from Merudo/fadeOut
Phergus Sep 10, 2019
6604900
Add DebounceExecutor, update ZoneRenderer.java to use debounced repai…
pnichols04 Sep 10, 2019
e4a1e8f
Add sound icons to the github directory
Merudo Sep 11, 2019
74ae270
Merge pull request #675 from Merudo/soundIcons
Phergus Sep 11, 2019
bb428ac
Add support for space in uri for stream functions
Merudo Sep 12, 2019
df153f6
Fix PRs automatically failed
Merudo Sep 12, 2019
c45f55b
Merge pull request #680 from Merudo/clientserverGradle
Phergus Sep 13, 2019
bf3f2d1
Merge branch 'develop' into convertUri
Phergus Sep 13, 2019
034aa70
Merge pull request #678 from Merudo/convertUri
Phergus Sep 13, 2019
63073e8
Fix bug: "*" stop working as path in stopStream, getStreamProperties …
Merudo Sep 13, 2019
358367c
Add propertyType option for getTokens(), improve getTokens() (#677)
Merudo Sep 13, 2019
f232bbd
Add support for space in uri for stream functions
Merudo Sep 12, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added build-resources/abeille-maptool-forms.jfpr
Binary file not shown.
10 changes: 8 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,11 @@ dependencies {
implementation group: 'org.apache.commons', name: 'commons-collections4', version: '4.1' // https://mvnrepository.com/artifact/org.apache.commons/commons-collections4

implementation 'net.java.abeille:abeille-formsrt:2.0'
implementation 'net.rptools.clientserver:clientserver:1.4.0.+'

// sourceControl gitRepository currently not producing classpath for Eclipse
// using jitpack.io for now
// implementation 'net.rptools.clientserver:clientserver:1.4.0.+'
implementation 'com.github.RPTools:clientserver:1.4.0.0'
implementation 'org.hibernate:antlr:2.7.5H3'

implementation 'commons-beanutils:commons-beanutils-core:1.8.3'
Expand All @@ -177,7 +181,7 @@ dependencies {
implementation 'net.rptools.decktool:decktool:1.0.b1'

implementation 'net.rptools.maptool.resource:maptool.resource:1.0.b18'
implementation 'net.rptools.parser:parser:1.4.0.+'
implementation 'com.github.RPTools:parser:1.5.4'

implementation 'jide-common:jide-common:3.2.3'
implementation 'jide-components:jide-components:3.2.3'
Expand Down Expand Up @@ -215,6 +219,8 @@ dependencies {
implementation 'yasb:yasb:0.2-21012007'
implementation 'de.muntjak.tinylookandfeel:tinylaf-nocp:1.4.0'

implementation 'com.jayway.jsonpath:json-path:2.4.0'

// For PDF image extraction
implementation 'org.apache.pdfbox:pdfbox:2.0.10'
implementation 'org.bouncycastle:bcmail-jdk15on:1.59' // To decrypt passworded/secured pdf's
Expand Down
233 changes: 137 additions & 96 deletions src/main/java/net/rptools/lib/swing/ImagePanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,38 +14,15 @@
*/
package net.rptools.lib.swing;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.*;
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.awt.dnd.DragSourceMotionListener;
import java.awt.dnd.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
import javax.swing.Scrollable;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.*;
import net.rptools.lib.CodeTimer;

@SuppressWarnings("serial")
Expand All @@ -55,6 +32,7 @@ public class ImagePanel extends JComponent
DragSourceListener,
MouseListener,
DragSourceMotionListener {

public enum SelectionMode {
SINGLE,
MULTIPLE,
Expand All @@ -64,7 +42,8 @@ public enum SelectionMode {
private ImagePanelModel model;

private int gridSize = 50;
private final int gridPadding = 5;
private final Dimension gridPadding = new Dimension(9, 11);
private final int captionPadding = 5;

private final Map<Rectangle, Integer> imageBoundsMap = new HashMap<Rectangle, Integer>();

Expand All @@ -77,7 +56,7 @@ public enum SelectionMode {
private final List<Object> selectedIDList = new ArrayList<Object>();
private final List<SelectionListener> selectionListenerList = new ArrayList<SelectionListener>();

private int fontHeight;
private int fontHeight = -1;

public ImagePanel() {
DragSource.getDefaultDragSource()
Expand All @@ -90,14 +69,45 @@ public ImagePanel() {
toolTipManager.registerComponent(this);
}

/**
* Ensures that the font height has been set. Needed for methods that do measuring outside the
* paint loop.
*
* @param g The graphics context from which to obtain font metrics. If this is null, the method
* will create and dispose its own graphics context.
*/
private void ensureFontHeight(Graphics2D g) {
if (fontHeight == -1) {
boolean mustDisposeGraphics = false;
if (g == null) {
g =
Objects.requireNonNullElseGet(
(Graphics2D) getGraphics(),
() -> {
var img =
GraphicsEnvironment.getLocalGraphicsEnvironment()
.getDefaultScreenDevice()
.getDefaultConfiguration()
.createCompatibleImage(1, 1, Transparency.OPAQUE);
return (Graphics2D) img.getGraphics();
});
mustDisposeGraphics = true;
}
fontHeight = g.getFontMetrics(UIManager.getFont("Label.font")).getHeight();
if (mustDisposeGraphics) {
g.dispose();
}
}
}

public void setGridSize(int size) {
// Min
if (size < 25) {
size = 25;
size = Math.min(25, size);
if (size != gridSize) {
gridSize = size;
revalidate();
repaint();
}
gridSize = size;
revalidate();
repaint();
}

public int getGridSize() {
Expand All @@ -109,35 +119,44 @@ public void setDraggingEnabled(boolean enabled) {
}

public void setSelectionMode(SelectionMode mode) {
selectionMode = mode;
selectedIDList.clear();
repaint();
if (selectionMode != mode) {
selectionMode = mode;
selectedIDList.clear();
repaint();
}
}

public void setShowCaptions(boolean enabled) {
showCaptions = enabled;
repaint();
if (showCaptions != enabled) {
showCaptions = enabled;
repaint();
}
}

public void setShowImageBorders(boolean enabled) {
showImageBorder = enabled;
repaint();
if (showImageBorder != enabled) {
showImageBorder = enabled;
repaint();
}
}

public ImagePanelModel getModel() {
return model;
}

public void setModel(ImagePanelModel model) {
this.model = model;
revalidate();
final JScrollPane scrollPane =
(JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, this);

if (scrollPane != null) {
scrollPane.setWheelScrollingEnabled(true);
scrollPane.revalidate();
scrollPane.repaint();
if (this.model != model) {
this.model = model;
revalidate();

final JScrollPane scrollPane =
(JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, this);

if (scrollPane != null) {
scrollPane.setWheelScrollingEnabled(true);
scrollPane.revalidate();
scrollPane.repaint();
}
}
}

Expand Down Expand Up @@ -166,13 +185,15 @@ public boolean isOpaque() {
}

@Override
protected void paintComponent(Graphics g) {
protected void paintComponent(Graphics gfx) {
var g = (Graphics2D) gfx;
CodeTimer timer = new CodeTimer("ImagePanel.paintComponent");
timer.setEnabled(false); // Change this to turn on perf data to System.out

Rectangle clipBounds = g.getClipBounds();

Dimension size = getSize();
var savedFont = g.getFont();
g.setFont(UIManager.getFont("Label.font"));
FontMetrics fm = g.getFontMetrics();
fontHeight = fm.getHeight();

Expand All @@ -184,40 +205,55 @@ protected void paintComponent(Graphics g) {
}
imageBoundsMap.clear();

int x = gridPadding;
int y = gridPadding;
int x = gridPadding.width;
int y = gridPadding.height;
int numToProcess = model.getImageCount();
String timerField = null;
if (timer.isEnabled()) {
timerField = "time to process " + numToProcess + " images";
timer.start(timerField);
}
for (int i = 0; i < numToProcess; i++) {
Image image = model.getImage(i);
Image image;

Rectangle bounds = new Rectangle(x, y, gridSize, gridSize);
imageBoundsMap.put(bounds, i);
imageBoundsMap.put(
new Rectangle(
x, y, gridSize, gridSize + (showCaptions ? captionPadding + fontHeight : 0)),
i);

// Background
Paint paint = model.getBackground(i);
if (paint != null) {
((Graphics2D) g).setPaint(paint);
g.setPaint(paint);
g.fillRect(x - 2, y - 2, gridSize + 4, gridSize + 4); // bleed out a little
}
if (image != null && bounds.intersects(clipBounds)) {
Dimension dim = constrainSize(image, gridSize);
g.drawImage(
image,
x + (gridSize - dim.width) / 2,
y + (gridSize - dim.height) / 2,
dim.width,
dim.height,
this);

// Image border
if (showImageBorder) {
g.setColor(Color.black);
g.drawRect(bounds.x, bounds.y, bounds.width, bounds.height);
if (bounds.intersects(clipBounds)) {
image = model.getImage(i);
if (image != null) {
Dimension dim = constrainSize(image, gridSize);
var savedRenderingHints = g.getRenderingHints();
if (dim.width < image.getWidth(null) || dim.height < image.getHeight(null)) {
g.setRenderingHint(
RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
} else if (dim.width > image.getWidth(null) || dim.height > image.getHeight(null)) {
g.setRenderingHint(
RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
}
g.drawImage(
image,
x + (gridSize - dim.width) / 2,
y + (gridSize - dim.height) / 2,
dim.width,
dim.height,
this);

// Image border
g.setRenderingHints(savedRenderingHints);
if (showImageBorder) {
g.setColor(Color.black);
g.drawRect(bounds.x, bounds.y, bounds.width, bounds.height);
}
}
}
// Selected
Expand Down Expand Up @@ -250,31 +286,34 @@ protected void paintComponent(Graphics g) {
if (caption != null) {
boolean nameTooLong = false;
int strWidth = fm.stringWidth(caption);
while (strWidth > bounds.width) {
nameTooLong = true;
caption = caption.substring(0, caption.length() - 1);
strWidth = fm.stringWidth(caption + "...");
}
if (nameTooLong) {
caption += "...";
if (strWidth > bounds.width) {
var avgCharWidth = (double) strWidth / caption.length();
var fittableChars = (int) (bounds.width / avgCharWidth);
caption = String.format("%s...", caption.substring(0, fittableChars - 2));
strWidth = fm.stringWidth(caption);
}
int cx = x + (gridSize - strWidth) / 2;
int cy = y + gridSize + fm.getHeight();

g.setColor(getForeground());
var savedRenderingHints = g.getRenderingHints();
g.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.drawString(caption, cx, cy);
g.setRenderingHints(savedRenderingHints);
}
}
// Line wrap
x += gridSize + gridPadding;
if (x > size.width - gridPadding - gridSize) {
x = gridPadding;
y += gridSize + gridPadding;
x += gridSize + gridPadding.width;
if ((x + gridSize) > (size.width - gridPadding.width)) {
x = gridPadding.width;
y += gridSize + gridPadding.height;
if (showCaptions) {
y += fontHeight;
}
}
}
g.setFont(savedFont);
if (timer.isEnabled()) {
timer.stop(timerField);
System.out.println(timer);
Expand Down Expand Up @@ -322,22 +361,23 @@ private Dimension constrainSize(Image image, int size) {

@Override
public Dimension getPreferredSize() {
int width = getSize().width;
if (model == null || model.getImageCount() == 0) {
return new Dimension();
}

ensureFontHeight(null);
int width = getWidth();

int rowCount = 0;
if (width < gridSize + gridPadding * 2) {
rowCount = model != null ? model.getImageCount() : 0;
int itemWidth = gridSize + gridPadding.width;
int itemHeight =
gridSize + gridPadding.height + (showCaptions ? fontHeight + captionPadding : 0);
int rowCount;
if (width < gridSize + gridPadding.width * 2) {
rowCount = model.getImageCount();
} else {
rowCount =
(int)
(model != null
? Math.ceil(model.getImageCount() / Math.floor(width / (gridSize + gridPadding)))
: 0);
rowCount = model.getImageCount() / (width / itemWidth);
}
int height =
(model != null
? rowCount * (gridSize + gridPadding + fontHeight) + gridPadding
: gridSize + gridPadding);
int height = rowCount * itemHeight;
return new Dimension(width, height);
}

Expand Down Expand Up @@ -371,7 +411,8 @@ public Dimension getPreferredScrollableViewportSize() {
}

public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return (gridSize + gridPadding) * 2;
ensureFontHeight(null);
return ((gridSize + gridPadding.height * 2) + (showCaptions ? fontHeight + captionPadding : 0));
}

public boolean getScrollableTracksViewportHeight() {
Expand Down
Loading