diff --git a/ts3-client/core/src/main/java/com/ts3client/net/IconRepository.java b/ts3-client/core/src/main/java/com/ts3client/net/IconRepository.java index ad31867..286fd1c 100644 --- a/ts3-client/core/src/main/java/com/ts3client/net/IconRepository.java +++ b/ts3-client/core/src/main/java/com/ts3client/net/IconRepository.java @@ -118,6 +118,9 @@ public final class IconRepository { icons.put(id, data); writeDiskCache(id, data); if (onIconLoaded != null) onIconLoaded.run(); + } catch (IllegalStateException e) { + // Not connected (yet): a channel icon can be asked for while the tree is + // first painted, before file transfers are up. Leave it retryable. } catch (Exception e) { // Missing or permission-denied icons are common; don't ask again. failed.add(id); diff --git a/ts3-client/swing/src/main/java/com/ts3client/ui/ServerTreePanel.java b/ts3-client/swing/src/main/java/com/ts3client/ui/ServerTreePanel.java index 4c6c493..8a100ca 100644 --- a/ts3-client/swing/src/main/java/com/ts3client/ui/ServerTreePanel.java +++ b/ts3-client/swing/src/main/java/com/ts3client/ui/ServerTreePanel.java @@ -11,6 +11,7 @@ import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JScrollPane; import javax.swing.JTree; +import javax.swing.JViewport; import javax.swing.SwingUtilities; import javax.swing.TransferHandler; import javax.swing.tree.DefaultMutableTreeNode; @@ -96,6 +97,9 @@ public final class ServerTreePanel extends JScrollPane { tree.setCellRenderer(new Renderer()); setViewportView(tree); getViewport().setBackground(Theme.TREE_BG); + // The icon strip is drawn against the viewport's right edge, so the blitted + // pixels a scroll would reuse are stale; repaint the whole viewport instead. + getViewport().setScrollMode(JViewport.SIMPLE_SCROLL_MODE); // Within the tree a drag moves the client or channel; dropped elsewhere it // yields the TS3 link BBCode, which the chat input accepts as plain text. @@ -426,6 +430,17 @@ public final class ServerTreePanel extends JScrollPane { super(model); } + /** + * Widens every repaint request to the full visible width. Swing only asks for + * the row rectangle, which stops short of the right-aligned icon strip and would + * leave it behind when a row's label changes width. + */ + @Override + public void repaint(long tm, int x, int y, int width, int height) { + Rectangle visible = getVisibleRect(); + super.repaint(tm, visible.x, y, visible.width, height); + } + void highlightChannel(TreePath path) { if (path == highlight || (path != null && path.equals(highlight))) return; highlight = path;