From 01e945a0c9fbd6fe40bfca59d42b1adf44896b45 Mon Sep 17 00:00:00 2001 From: James Shelton Date: Mon, 2 Dec 2024 17:55:52 +0000 Subject: [PATCH 01/10] Trigger toggle button action from popup menu (fixes #74) --- .../reldo/taskstracker/panel/components/MultiToggleButton.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/reldo/taskstracker/panel/components/MultiToggleButton.java b/src/main/java/net/reldo/taskstracker/panel/components/MultiToggleButton.java index 6c4fc47..3be22c6 100644 --- a/src/main/java/net/reldo/taskstracker/panel/components/MultiToggleButton.java +++ b/src/main/java/net/reldo/taskstracker/panel/components/MultiToggleButton.java @@ -142,7 +142,7 @@ public void setStateThenAction(int state) private void addPopupMenuItem(String text, int state) { JMenuItem menuItem = new JMenuItem(text); - menuItem.addActionListener(e -> {if(isEnabled())setState(state);}); + menuItem.addActionListener(e -> {if(isEnabled())setStateThenAction(state);}); popupMenu.add(menuItem); } } From 00b3a9e3ed4087122ce1443b80c4b702a4c5ba6b Mon Sep 17 00:00:00 2001 From: James Shelton Date: Fri, 6 Dec 2024 18:45:16 +0000 Subject: [PATCH 02/10] Ignore profile changes until start up completed (#80) --- .../java/net/reldo/taskstracker/TasksTrackerPlugin.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/reldo/taskstracker/TasksTrackerPlugin.java b/src/main/java/net/reldo/taskstracker/TasksTrackerPlugin.java index 1106041..723c4ef 100644 --- a/src/main/java/net/reldo/taskstracker/TasksTrackerPlugin.java +++ b/src/main/java/net/reldo/taskstracker/TasksTrackerPlugin.java @@ -87,6 +87,7 @@ public class TasksTrackerPlugin extends Plugin private NavigationButton navButton; private RuneScapeProfileType currentProfileType; private final Map oldExperience = new EnumMap<>(Skill.class); + private boolean startUpCompleted = false; @Inject @Named("runelite.version") private String runeliteVersion; @Inject private Gson gson; @@ -149,6 +150,7 @@ protected void startUp() .build(); clientToolbar.addNavigation(navButton); + startUpCompleted = true; log.info("Tasks Tracker started!"); } @@ -158,6 +160,7 @@ protected void shutDown() pluginPanel = null; taskService.clearTaskTypes(); clientToolbar.removeNavigation(navButton); + startUpCompleted = false; log.info("Tasks Tracker stopped!"); } @@ -309,7 +312,10 @@ public void onStatChanged(StatChanged statChanged) @Subscribe public void onProfileChanged(ProfileChanged profileChanged) { - reloadTaskType(); + if (startUpCompleted) + { + reloadTaskType(); + } } public void refresh() From 0f19bb9b19f09e00b39baf2bdcb510c75f84188d Mon Sep 17 00:00:00 2001 From: James Shelton Date: Fri, 6 Dec 2024 22:24:15 +0000 Subject: [PATCH 03/10] Add filter button config for all task list tabs (#70) - All tabs are now user configurable - All tabs default to filter buttons enabled - Popup menu is removed when the button is disabled --- .../taskstracker/TasksTrackerConfig.java | 338 +++++++++++++++++- .../taskstracker/TasksTrackerPlugin.java | 7 + .../taskstracker/config/ConfigValues.java | 51 ++- .../taskstracker/panel/LoggedInPanel.java | 221 ++++++------ .../panel/TasksTrackerPluginPanel.java | 8 + .../panel/components/MultiToggleButton.java | 8 +- 6 files changed, 502 insertions(+), 131 deletions(-) diff --git a/src/main/java/net/reldo/taskstracker/TasksTrackerConfig.java b/src/main/java/net/reldo/taskstracker/TasksTrackerConfig.java index fbaa4a2..aa633b8 100644 --- a/src/main/java/net/reldo/taskstracker/TasksTrackerConfig.java +++ b/src/main/java/net/reldo/taskstracker/TasksTrackerConfig.java @@ -4,15 +4,29 @@ import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.ConfigSection; @ConfigGroup(TasksTrackerPlugin.CONFIG_GROUP_NAME) public interface TasksTrackerConfig extends Config { + + /*==================== + -- General settings -- + ====================*/ + + @ConfigSection( + name = "General", + description = "General settings", + position = 0 + ) + String generalSettings = "generalSettings"; + @ConfigItem( - position = 10, - keyName = "untrackUponCompletion", - name = "Untrack Tasks Upon Completion", - description = "Configures whether completed tasks should also automatically untracked when the task is completed." + position = 10, + keyName = "untrackUponCompletion", + name = "Untrack Tasks Upon Completion", + description = "Configures whether completed tasks should also automatically untracked when the task is completed.", + section = generalSettings ) default boolean untrackUponCompletion() { @@ -23,7 +37,8 @@ default boolean untrackUponCompletion() position = 11, keyName = "filterPanelCollapsible", name = "Filter Panels Collapsible", - description = "Shows button that allows filter panels to be hidden." + description = "Shows button that allows filter panels to be hidden.", + section = generalSettings ) default boolean filterPanelCollapsible() { @@ -87,15 +102,15 @@ default ConfigValues.IgnoredFilterValues ignoredFilter() ) default ConfigValues.TaskListTabs taskListTab() { - return ConfigValues.TaskListTabs.ALL; + return ConfigValues.TaskListTabs.TAB_TWO; } @ConfigItem( - position = 106, - keyName = "taskTypeJsonName", - name = "Task Type", - description = "Configures the task type which is displayed in the panel.", - hidden = true + position = 106, + keyName = "taskTypeJsonName", + name = "Task Type", + description = "Configures the task type which is displayed in the panel.", + hidden = true ) default String taskTypeJsonName() { @@ -103,11 +118,11 @@ default String taskTypeJsonName() } @ConfigItem( - position = 109, - keyName = "dropdownFilter", - name = "Dropdown Filter", - description = "Configures the dropdown to filter tasks on.", - hidden = true + position = 109, + keyName = "dropdownFilter", + name = "Dropdown Filter", + description = "Configures the dropdown to filter tasks on.", + hidden = true ) default String dropdownFilter() { @@ -137,4 +152,295 @@ default ConfigValues.SortDirections sortDirection() { return ConfigValues.SortDirections.ASCENDING; } + + /*========================== + -- Task List Tab settings -- + ==========================*/ + + /*================== + -- Tab 1 settings -- + ==================*/ + + @ConfigSection( + name = "Task List Tab 1", + description = "Tab 1 settings", + position = 1 + ) + String tab1Settings = "tab1Settings"; + + @ConfigItem( + position = 1, + keyName = "tab1Name", + name = "Name", + description = "The name of the tab. Default: Tracked Tasks", + section = tab1Settings + ) + default String tab1Name() + { + return "Tracked Tasks"; + } + + @ConfigItem( + position = 2, + keyName = "tab1CompletedLock", + name = "Lock Completed Filter", + description = "Locks the completed tasks filter button to the configured value when tab 1 is selected.", + section = tab1Settings + ) + default boolean tab1CompletedLock() + { + return false; + } + + @ConfigItem( + position = 3, + keyName = "tab1CompletedValue", + name = "Completed Filter", + description = "The configured completed tasks filter button value.", + section = tab1Settings + ) + default ConfigValues.CompletedFilterValues tab1CompletedValue() + { + return ConfigValues.CompletedFilterValues.COMPLETE_AND_INCOMPLETE; + } + + @ConfigItem( + position = 4, + keyName = "tab1TrackedLock", + name = "Lock Tracked Filter", + description = "Locks the tracked tasks filter button to the configured value when tab 1 is selected.", + section = tab1Settings + ) + default boolean tab1TrackedLock() + { + return false; + } + + @ConfigItem( + position = 5, + keyName = "tab1TrackedValue", + name = "Tracked Filter", + description = "The configured tracked tasks filter button value.", + section = tab1Settings + ) + default ConfigValues.TrackedFilterValues tab1TrackedValue() + { + return ConfigValues.TrackedFilterValues.TRACKED; + } + + @ConfigItem( + position = 6, + keyName = "tab1IgnoredLock", + name = "Lock Ignored Filter", + description = "Locks the ignored tasks filter button to the configured value when tab 1 is selected.", + section = tab1Settings + ) + default boolean tab1IgnoredLock() + { + return false; + } + + @ConfigItem( + position = 7, + keyName = "tab1IgnoredValue", + name = "Ignored Filter", + description = "The configured ignored tasks filter button value.", + section = tab1Settings + ) + default ConfigValues.IgnoredFilterValues tab1IgnoredValue() + { + return ConfigValues.IgnoredFilterValues.NOT_IGNORED; + } + + /*================== + -- Tab 2 settings -- + ==================*/ + + @ConfigSection( + name = "Task List Tab 2", + description = "Tab 2 settings", + position = 2 + ) + String tab2Settings = "tab2Settings"; + + @ConfigItem( + position = 1, + keyName = "tab2Name", + name = "Name", + description = "The name of the tab. Default: All Tasks", + section = tab2Settings + ) + default String tab2Name() + { + return "All Tasks"; + } + + @ConfigItem( + position = 2, + keyName = "tab2CompletedLock", + name = "Lock Completed Filter", + description = "Locks the completed tasks filter button to the configured value when tab 2 is selected.", + section = tab2Settings + ) + default boolean tab2CompletedLock() + { + return false; + } + + @ConfigItem( + position = 3, + keyName = "tab2CompletedValue", + name = "Completed Filter", + description = "The configured completed tasks filter button value.", + section = tab2Settings + ) + default ConfigValues.CompletedFilterValues tab2CompletedValue() + { + return ConfigValues.CompletedFilterValues.COMPLETE_AND_INCOMPLETE; + } + + @ConfigItem( + position = 4, + keyName = "tab2TrackedLock", + name = "Lock Tracked Filter", + description = "Locks the tracked tasks filter button to the configured value when tab 2 is selected.", + section = tab2Settings + ) + default boolean tab2TrackedLock() + { + return false; + } + + @ConfigItem( + position = 5, + keyName = "tab2TrackedValue", + name = "Tracked Filter", + description = "The configured tracked tasks filter button value.", + section = tab2Settings + ) + default ConfigValues.TrackedFilterValues tab2TrackedValue() + { + return ConfigValues.TrackedFilterValues.TRACKED_AND_UNTRACKED; + } + + @ConfigItem( + position = 6, + keyName = "tab2IgnoredLock", + name = "Lock Ignored Filter", + description = "Locks the ignored tasks filter button to the configured value when tab 2 is selected.", + section = tab2Settings + ) + default boolean tab2IgnoredLock() + { + return false; + } + + @ConfigItem( + position = 7, + keyName = "tab2IgnoredValue", + name = "Ignored Filter", + description = "The configured ignored tasks filter button value.", + section = tab2Settings + ) + default ConfigValues.IgnoredFilterValues tab2IgnoredValue() + { + return ConfigValues.IgnoredFilterValues.IGNORED_AND_NOT_IGNORED; + } + + /*================== + -- Tab 3 settings -- + ==================*/ + + @ConfigSection( + name = "Task List Tab 3", + description = "Tab 3 settings", + position = 3 + ) + String tab3Settings = "tab3Settings"; + + @ConfigItem( + position = 1, + keyName = "tab3Name", + name = "Name", + description = "The name of the tab. Default: Custom", + section = tab3Settings + ) + default String tab3Name() + { + return "Custom"; + } + + @ConfigItem( + position = 2, + keyName = "tab3CompletedLock", + name = "Lock Completed Filter", + description = "Locks the completed tasks filter button to the configured value when tab 3 is selected.", + section = tab3Settings + ) + default boolean tab3CompletedLock() + { + return false; + } + + @ConfigItem( + position = 3, + keyName = "tab3CompletedValue", + name = "Completed Filter", + description = "The configured completed tasks filter button value.", + section = tab3Settings + ) + default ConfigValues.CompletedFilterValues tab3CompletedValue() + { + return ConfigValues.CompletedFilterValues.COMPLETE_AND_INCOMPLETE; + } + + @ConfigItem( + position = 4, + keyName = "tab3TrackedLock", + name = "Lock Tracked Filter", + description = "Locks the tracked tasks filter button to the configured value when tab 3 is selected.", + section = tab3Settings + ) + default boolean tab3TrackedLock() + { + return false; + } + + @ConfigItem( + position = 5, + keyName = "tab3TrackedValue", + name = "Tracked Filter", + description = "The configured tracked tasks filter button value.", + section = tab3Settings + ) + default ConfigValues.TrackedFilterValues tab3TrackedValue() + { + return ConfigValues.TrackedFilterValues.TRACKED_AND_UNTRACKED; + } + + @ConfigItem( + position = 6, + keyName = "tab3IgnoredLock", + name = "Lock Ignored Filter", + description = "Locks the ignored tasks filter button to the configured value when tab 3 is selected.", + section = tab3Settings + ) + default boolean tab3IgnoredLock() + { + return false; + } + + @ConfigItem( + position = 7, + keyName = "tab3IgnoredValue", + name = "Ignored Filter", + description = "The configured ignored tasks filter button value.", + section = tab3Settings + ) + default ConfigValues.IgnoredFilterValues tab3IgnoredValue() + { + return ConfigValues.IgnoredFilterValues.NOT_IGNORED; + } + + } diff --git a/src/main/java/net/reldo/taskstracker/TasksTrackerPlugin.java b/src/main/java/net/reldo/taskstracker/TasksTrackerPlugin.java index 723c4ef..78d8f6a 100644 --- a/src/main/java/net/reldo/taskstracker/TasksTrackerPlugin.java +++ b/src/main/java/net/reldo/taskstracker/TasksTrackerPlugin.java @@ -210,6 +210,7 @@ public void onConfigChanged(ConfigChanged configChanged) { return; } + log.debug("onConfigChanged {} {}", configChanged.getKey(), configChanged.getNewValue()); if (configChanged.getKey().equals("untrackUponCompletion") && config.untrackUponCompletion()) { @@ -220,6 +221,12 @@ public void onConfigChanged(ConfigChanged configChanged) { pluginPanel.redraw(); } + + if (configChanged.getKey().startsWith("tab")) // task list tab config items all start 'tab#' + { + pluginPanel.refreshFilterButtonsFromConfig(config.taskListTab().ordinal() + 1); + refresh(); + } } @Subscribe diff --git a/src/main/java/net/reldo/taskstracker/config/ConfigValues.java b/src/main/java/net/reldo/taskstracker/config/ConfigValues.java index 21c7ac2..8135c99 100644 --- a/src/main/java/net/reldo/taskstracker/config/ConfigValues.java +++ b/src/main/java/net/reldo/taskstracker/config/ConfigValues.java @@ -5,30 +5,57 @@ public class ConfigValues { public enum CompletedFilterValues { - COMPLETE_AND_INCOMPLETE, - COMPLETE, - INCOMPLETE; + COMPLETE_AND_INCOMPLETE("Both"), + COMPLETE("Complete"), + INCOMPLETE("Incomplete"); + + public final String name; + + public String toString() { return name; } + + CompletedFilterValues(String name) + { + this.name = name; + } } public enum TrackedFilterValues { - TRACKED_AND_UNTRACKED, - TRACKED, - UNTRACKED; + TRACKED_AND_UNTRACKED("Both"), + TRACKED("Tracked"), + UNTRACKED("Untracked"); + + public final String name; + + public String toString() { return name; } + + TrackedFilterValues(String name) + { + this.name = name; + } } public enum IgnoredFilterValues { - NOT_IGNORED, - IGNORED_AND_NOT_IGNORED, - IGNORED; + NOT_IGNORED("Not Ignored"), + IGNORED_AND_NOT_IGNORED("Both"), + IGNORED("Ignored"); + + public final String name; + + public String toString() { return name; } + + IgnoredFilterValues(String name) + { + this.name = name; + } } public enum TaskListTabs { - TRACKED, - ALL, - CUSTOM; + TAB_ONE, + TAB_TWO, + TAB_THREE; } public enum SortDirections diff --git a/src/main/java/net/reldo/taskstracker/panel/LoggedInPanel.java b/src/main/java/net/reldo/taskstracker/panel/LoggedInPanel.java index 67bb9ba..4913e9d 100644 --- a/src/main/java/net/reldo/taskstracker/panel/LoggedInPanel.java +++ b/src/main/java/net/reldo/taskstracker/panel/LoggedInPanel.java @@ -62,6 +62,9 @@ public class LoggedInPanel extends JPanel private SubFilterPanel subFilterPanel; private SortPanel sortPanel; private final JToggleButton collapseBtn = new JToggleButton(); + private JToggleButton tabOne; + private JToggleButton tabTwo; + private JToggleButton tabThree; public LoggedInPanel(TasksTrackerPlugin plugin, TasksTrackerConfig config, TaskService taskService) { @@ -109,8 +112,8 @@ public void refresh(TaskFromStruct task) if(task == null) { updateCollapseButtonText(); + refreshTabNames(); } - taskListPanel.refresh(task); } @@ -124,14 +127,6 @@ private void createPanel() add(getNorthPanel(), BorderLayout.NORTH); add(getCenterPanel(), BorderLayout.CENTER); add(getSouthPanel(), BorderLayout.SOUTH); - - loadAndApplyFilters(config.taskListTab()); - if(config.taskListTab().equals(ConfigValues.TaskListTabs.TRACKED)) - { - trackedFilterBtn.setState(1); - trackedFilterBtn.setEnabled(false); - plugin.getConfigManager().setConfiguration(TasksTrackerPlugin.CONFIG_GROUP_NAME, "trackedFilter", ConfigValues.TrackedFilterValues.TRACKED); - } } private JPanel getCenterPanel() { @@ -145,47 +140,37 @@ private JPanel getCenterPanel() { tabPane.setBorder(new EmptyBorder(0,0,0,0)); tabPane.setPreferredSize(new Dimension(PluginPanel.PANEL_WIDTH,24)); - JToggleButton trackedTab = tabButton("Tracked Tasks", ConfigValues.TaskListTabs.TRACKED); - JToggleButton allTab = tabButton("All Tasks", ConfigValues.TaskListTabs.ALL); - JToggleButton customTab = tabButton("Custom", ConfigValues.TaskListTabs.CUSTOM); + tabOne = tabButton(config.tab1Name(), ConfigValues.TaskListTabs.TAB_ONE); + tabTwo = tabButton(config.tab2Name(), ConfigValues.TaskListTabs.TAB_TWO); + tabThree = tabButton(config.tab3Name(), ConfigValues.TaskListTabs.TAB_THREE); ButtonGroup tabGroup = new ButtonGroup(); - tabGroup.add(trackedTab); - tabGroup.add(allTab); - tabGroup.add(customTab); + tabGroup.add(tabOne); + tabGroup.add(tabTwo); + tabGroup.add(tabThree); tabPane.add(Box.createHorizontalGlue()); - tabPane.add(trackedTab); + tabPane.add(tabOne); tabPane.add(Box.createHorizontalGlue()); - tabPane.add(allTab); + tabPane.add(tabTwo); tabPane.add(Box.createHorizontalGlue()); - tabPane.add(customTab); + tabPane.add(tabThree); tabPane.add(Box.createHorizontalGlue()); taskListPanel.add(tabPane, BorderLayout.NORTH); taskListPanel.add(this.taskListPanel, BorderLayout.CENTER); - // set initial filter states to "complete and incomplete", "tracked and untracked", "not ignored" - Map filterStates = new HashMap<>(); - filterStates.put("completed",0); - filterStates.put("tracked",0); - filterStates.put("ignored",0); - for(ConfigValues.TaskListTabs tab : ConfigValues.TaskListTabs.values()) - { - filterStore.put(tab, filterStates); - } - switch (config.taskListTab()) { - case TRACKED: - trackedTab.setSelected(true); + case TAB_ONE: + tabOne.setSelected(true); break; - case ALL: - allTab.setSelected(true); + case TAB_TWO: + tabTwo.setSelected(true); break; - case CUSTOM: - customTab.setSelected(true); + case TAB_THREE: + tabThree.setSelected(true); break; } tabChanged(config.taskListTab()); @@ -195,97 +180,124 @@ private JPanel getCenterPanel() { public void tabChanged(ConfigValues.TaskListTabs newTab) { - if(newTab != null) { - changeTab(newTab); - - switch (newTab) { - case TRACKED: - trackedFilterBtn.setState(1); - trackedFilterBtn.setEnabled(false); - plugin.getConfigManager().setConfiguration(TasksTrackerPlugin.CONFIG_GROUP_NAME, "taskListTab", newTab); - filterButtonAction("tracked"); + if(newTab != null) + { + saveCurrentTabFilters(); + + switch (newTab) + { + case TAB_ONE: + plugin.getConfigManager().setConfiguration(TasksTrackerPlugin.CONFIG_GROUP_NAME, "taskListTab", newTab); + refreshFilterButtonsFromConfig(1); break; - case ALL: - trackedFilterBtn.setState(0); - trackedFilterBtn.setEnabled(false); - completedFilterBtn.setState(0); - completedFilterBtn.setEnabled(false); - ignoredFilterBtn.setState(1); - ignoredFilterBtn.setEnabled(false); - plugin.getConfigManager().setConfiguration(TasksTrackerPlugin.CONFIG_GROUP_NAME, "taskListTab", newTab); - actionAllFilterButtons(); + case TAB_TWO: + plugin.getConfigManager().setConfiguration(TasksTrackerPlugin.CONFIG_GROUP_NAME, "taskListTab", newTab); + refreshFilterButtonsFromConfig(2); break; - case CUSTOM: + case TAB_THREE: plugin.getConfigManager().setConfiguration(TasksTrackerPlugin.CONFIG_GROUP_NAME, "taskListTab", newTab); - plugin.refresh(); + refreshFilterButtonsFromConfig(3); break; default: - plugin.refresh(); break; } - } - } - private JToggleButton tabButton(String label, ConfigValues.TaskListTabs tab) - { - JToggleButton button = new JToggleButton(label); - - button.setBorder(new EmptyBorder(2,5,2,5)); - button.setBackground(ColorScheme.DARK_GRAY_COLOR); - button.setForeground(ColorScheme.LIGHT_GRAY_COLOR); - button.addActionListener(e -> tabChanged(tab)); - - return button; + plugin.refresh(); + } } - private void changeTab(ConfigValues.TaskListTabs newTab) + private void saveCurrentTabFilters() { - saveFilters(); - resetFilters(); - loadAndApplyFilters(newTab); - } + String tab = "tab" + (config.taskListTab().ordinal() + 1); // tabs are 1-indexed - private final Map> filterStore = new HashMap<>(); + Enum configValue; - private void saveFilters() - { - ConfigValues.TaskListTabs tab = config.taskListTab(); + if (plugin.getConfigManager().getConfiguration(TasksTrackerPlugin.CONFIG_GROUP_NAME, tab + "CompletedLock").equals("false")) + { + configValue = ConfigValues.CompletedFilterValues.values()[completedFilterBtn.getState()]; + plugin.getConfigManager().setConfiguration(TasksTrackerPlugin.CONFIG_GROUP_NAME, tab + "CompletedValue", configValue); + } - Map filterStates = new HashMap<>(); - filterStates.put("completed", config.completedFilter().ordinal()); - filterStates.put("tracked", config.trackedFilter().ordinal()); - filterStates.put("ignored", config.ignoredFilter().ordinal()); + if (plugin.getConfigManager().getConfiguration(TasksTrackerPlugin.CONFIG_GROUP_NAME, tab + "TrackedLock").equals("false")) + { + configValue = ConfigValues.TrackedFilterValues.values()[trackedFilterBtn.getState()]; + plugin.getConfigManager().setConfiguration(TasksTrackerPlugin.CONFIG_GROUP_NAME, tab + "TrackedValue", configValue); + } - filterStore.put(tab, filterStates); + if (plugin.getConfigManager().getConfiguration(TasksTrackerPlugin.CONFIG_GROUP_NAME, tab + "IgnoredLock").equals("false")) + { + configValue = ConfigValues.IgnoredFilterValues.values()[ignoredFilterBtn.getState()]; + plugin.getConfigManager().setConfiguration(TasksTrackerPlugin.CONFIG_GROUP_NAME, tab + "IgnoredValue", configValue); + } } - private void resetFilters() + // TODO reduce duplication + public void refreshFilterButtonsFromConfig(int tab) { - completedFilterBtn.setEnabled(true); - trackedFilterBtn.setEnabled(true); - ignoredFilterBtn.setEnabled(true); + switch (tab) + { + case 1: + trackedFilterBtn.setState(config.tab1TrackedValue().ordinal()); + trackedFilterBtn.setEnabled(!config.tab1TrackedLock()); + completedFilterBtn.setState(config.tab1CompletedValue().ordinal()); + completedFilterBtn.setEnabled(!config.tab1CompletedLock()); + ignoredFilterBtn.setState(config.tab1IgnoredValue().ordinal()); + ignoredFilterBtn.setEnabled(!config.tab1IgnoredLock()); + actionAllFilterButtonsNoRefresh(); + break; + case 2: + trackedFilterBtn.setState(config.tab2TrackedValue().ordinal()); + trackedFilterBtn.setEnabled(!config.tab2TrackedLock()); + completedFilterBtn.setState(config.tab2CompletedValue().ordinal()); + completedFilterBtn.setEnabled(!config.tab2CompletedLock()); + ignoredFilterBtn.setState(config.tab2IgnoredValue().ordinal()); + ignoredFilterBtn.setEnabled(!config.tab2IgnoredLock()); + actionAllFilterButtonsNoRefresh(); + break; + case 3: + trackedFilterBtn.setState(config.tab3TrackedValue().ordinal()); + trackedFilterBtn.setEnabled(!config.tab3TrackedLock()); + completedFilterBtn.setState(config.tab3CompletedValue().ordinal()); + completedFilterBtn.setEnabled(!config.tab3CompletedLock()); + ignoredFilterBtn.setState(config.tab3IgnoredValue().ordinal()); + ignoredFilterBtn.setEnabled(!config.tab3IgnoredLock()); + actionAllFilterButtonsNoRefresh(); + break; + default: + break; + } } - private void loadAndApplyFilters(ConfigValues.TaskListTabs tab) + private JToggleButton tabButton(String label, ConfigValues.TaskListTabs tab) { - Map filterStates = filterStore.get(tab); - - if(filterStates == null) return; - - Enum configValue; - - completedFilterBtn.setState(filterStates.get("completed")); - trackedFilterBtn.setState(filterStates.get("tracked")); - ignoredFilterBtn.setState(filterStates.get("ignored")); + JToggleButton button = new JToggleButton(label); - configValue = ConfigValues.CompletedFilterValues.values()[completedFilterBtn.getState()]; - plugin.getConfigManager().setConfiguration(TasksTrackerPlugin.CONFIG_GROUP_NAME, "completedFilter", configValue); + button.setBorder(new EmptyBorder(2,5,2,5)); + button.setBackground(ColorScheme.DARK_GRAY_COLOR); + button.setForeground(ColorScheme.LIGHT_GRAY_COLOR); + button.addActionListener(e -> tabChanged(tab)); - configValue = ConfigValues.TrackedFilterValues.values()[trackedFilterBtn.getState()]; - plugin.getConfigManager().setConfiguration(TasksTrackerPlugin.CONFIG_GROUP_NAME, "trackedFilter", configValue); + return button; + } - configValue = ConfigValues.IgnoredFilterValues.values()[ignoredFilterBtn.getState()]; - plugin.getConfigManager().setConfiguration(TasksTrackerPlugin.CONFIG_GROUP_NAME, "ignoredFilter", configValue); + private void refreshTabNames() + { + String tabName; + if (!tabOne.getText().equals(config.tab1Name())) + { + tabName = config.tab1Name().isBlank() ? "Tab 1" : config.tab1Name(); + tabOne.setText(tabName); + } + if (!tabTwo.getText().equals(config.tab2Name())) + { + tabName = config.tab2Name().isBlank() ? "Tab 2" : config.tab2Name(); + tabTwo.setText(tabName); + } + if (!tabThree.getText().equals(config.tab3Name())) + { + tabName = config.tab3Name().isBlank() ? "Tab 3" : config.tab3Name(); + tabThree.setText(tabName); + } } private JPanel getSouthPanel() @@ -483,11 +495,16 @@ private void filterButtonAction(String filter) plugin.refresh(); } - private void actionAllFilterButtons() + private void actionAllFilterButtonsNoRefresh() { filterButtonActionNoRefresh("tracked"); filterButtonActionNoRefresh("ignored"); filterButtonActionNoRefresh("completed"); + } + + private void actionAllFilterButtons() + { + actionAllFilterButtonsNoRefresh(); plugin.refresh(); } diff --git a/src/main/java/net/reldo/taskstracker/panel/TasksTrackerPluginPanel.java b/src/main/java/net/reldo/taskstracker/panel/TasksTrackerPluginPanel.java index a1429b2..04c2e88 100644 --- a/src/main/java/net/reldo/taskstracker/panel/TasksTrackerPluginPanel.java +++ b/src/main/java/net/reldo/taskstracker/panel/TasksTrackerPluginPanel.java @@ -64,6 +64,14 @@ public void refresh(TaskFromStruct task) } } + public void refreshFilterButtonsFromConfig(int tab) + { + if (loggedIn) + { + loggedInPanel.refreshFilterButtonsFromConfig(tab); + } + } + public void setLoggedIn(boolean loggedIn) { if(SwingUtilities.isEventDispatchThread()) diff --git a/src/main/java/net/reldo/taskstracker/panel/components/MultiToggleButton.java b/src/main/java/net/reldo/taskstracker/panel/components/MultiToggleButton.java index 3be22c6..0ce07f9 100644 --- a/src/main/java/net/reldo/taskstracker/panel/components/MultiToggleButton.java +++ b/src/main/java/net/reldo/taskstracker/panel/components/MultiToggleButton.java @@ -46,7 +46,7 @@ public void popupMenuEnabled(boolean enabled) } else { - this.remove(popupMenu); + this.setComponentPopupMenu(null); } } } @@ -145,4 +145,10 @@ private void addPopupMenuItem(String text, int state) menuItem.addActionListener(e -> {if(isEnabled())setStateThenAction(state);}); popupMenu.add(menuItem); } + + public void setEnabled(boolean enabled) + { + super.setEnabled(enabled); + popupMenuEnabled(enabled); + } } From 3b85f8090bdc00d88445f00dd333dedc2c0fd50c Mon Sep 17 00:00:00 2001 From: James Shelton Date: Mon, 9 Dec 2024 16:08:52 +0000 Subject: [PATCH 04/10] Revert "Ignore profile changes until start up completed (#80)" This reverts commit 00b3a9e3ed4087122ce1443b80c4b702a4c5ba6b. --- .../java/net/reldo/taskstracker/TasksTrackerPlugin.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/main/java/net/reldo/taskstracker/TasksTrackerPlugin.java b/src/main/java/net/reldo/taskstracker/TasksTrackerPlugin.java index 78d8f6a..14f808f 100644 --- a/src/main/java/net/reldo/taskstracker/TasksTrackerPlugin.java +++ b/src/main/java/net/reldo/taskstracker/TasksTrackerPlugin.java @@ -87,7 +87,6 @@ public class TasksTrackerPlugin extends Plugin private NavigationButton navButton; private RuneScapeProfileType currentProfileType; private final Map oldExperience = new EnumMap<>(Skill.class); - private boolean startUpCompleted = false; @Inject @Named("runelite.version") private String runeliteVersion; @Inject private Gson gson; @@ -150,7 +149,6 @@ protected void startUp() .build(); clientToolbar.addNavigation(navButton); - startUpCompleted = true; log.info("Tasks Tracker started!"); } @@ -160,7 +158,6 @@ protected void shutDown() pluginPanel = null; taskService.clearTaskTypes(); clientToolbar.removeNavigation(navButton); - startUpCompleted = false; log.info("Tasks Tracker stopped!"); } @@ -319,10 +316,7 @@ public void onStatChanged(StatChanged statChanged) @Subscribe public void onProfileChanged(ProfileChanged profileChanged) { - if (startUpCompleted) - { - reloadTaskType(); - } + reloadTaskType(); } public void refresh() From e53ea8878159e29a68f03de8f64ee54e83331ed0 Mon Sep 17 00:00:00 2001 From: James Shelton Date: Tue, 10 Dec 2024 21:24:17 +0000 Subject: [PATCH 05/10] Ensure configured tab is selected when switching profile --- .../taskstracker/TasksTrackerPlugin.java | 3 +- .../taskstracker/panel/LoggedInPanel.java | 32 ++++++------------- .../panel/TasksTrackerPluginPanel.java | 3 +- 3 files changed, 13 insertions(+), 25 deletions(-) diff --git a/src/main/java/net/reldo/taskstracker/TasksTrackerPlugin.java b/src/main/java/net/reldo/taskstracker/TasksTrackerPlugin.java index 14f808f..472dafb 100644 --- a/src/main/java/net/reldo/taskstracker/TasksTrackerPlugin.java +++ b/src/main/java/net/reldo/taskstracker/TasksTrackerPlugin.java @@ -221,7 +221,7 @@ public void onConfigChanged(ConfigChanged configChanged) if (configChanged.getKey().startsWith("tab")) // task list tab config items all start 'tab#' { - pluginPanel.refreshFilterButtonsFromConfig(config.taskListTab().ordinal() + 1); + pluginPanel.refreshFilterButtonsFromConfig(config.taskListTab()); refresh(); } } @@ -340,6 +340,7 @@ public void reloadTaskType() SwingUtilities.invokeLater(() -> { pluginPanel.redraw(); + pluginPanel.refreshFilterButtonsFromConfig(config.taskListTab()); pluginPanel.refresh(null); }); } diff --git a/src/main/java/net/reldo/taskstracker/panel/LoggedInPanel.java b/src/main/java/net/reldo/taskstracker/panel/LoggedInPanel.java index 4913e9d..66b8f00 100644 --- a/src/main/java/net/reldo/taskstracker/panel/LoggedInPanel.java +++ b/src/main/java/net/reldo/taskstracker/panel/LoggedInPanel.java @@ -183,25 +183,8 @@ public void tabChanged(ConfigValues.TaskListTabs newTab) if(newTab != null) { saveCurrentTabFilters(); - - switch (newTab) - { - case TAB_ONE: - plugin.getConfigManager().setConfiguration(TasksTrackerPlugin.CONFIG_GROUP_NAME, "taskListTab", newTab); - refreshFilterButtonsFromConfig(1); - break; - case TAB_TWO: - plugin.getConfigManager().setConfiguration(TasksTrackerPlugin.CONFIG_GROUP_NAME, "taskListTab", newTab); - refreshFilterButtonsFromConfig(2); - break; - case TAB_THREE: - plugin.getConfigManager().setConfiguration(TasksTrackerPlugin.CONFIG_GROUP_NAME, "taskListTab", newTab); - refreshFilterButtonsFromConfig(3); - break; - default: - break; - } - + plugin.getConfigManager().setConfiguration(TasksTrackerPlugin.CONFIG_GROUP_NAME, "taskListTab", newTab); + refreshFilterButtonsFromConfig(newTab); plugin.refresh(); } } @@ -232,11 +215,12 @@ private void saveCurrentTabFilters() } // TODO reduce duplication - public void refreshFilterButtonsFromConfig(int tab) + public void refreshFilterButtonsFromConfig(ConfigValues.TaskListTabs tab) { switch (tab) { - case 1: + case TAB_ONE: + if(!tabOne.isSelected()) tabOne.setSelected(true); trackedFilterBtn.setState(config.tab1TrackedValue().ordinal()); trackedFilterBtn.setEnabled(!config.tab1TrackedLock()); completedFilterBtn.setState(config.tab1CompletedValue().ordinal()); @@ -245,7 +229,8 @@ public void refreshFilterButtonsFromConfig(int tab) ignoredFilterBtn.setEnabled(!config.tab1IgnoredLock()); actionAllFilterButtonsNoRefresh(); break; - case 2: + case TAB_TWO: + if(!tabTwo.isSelected()) tabTwo.setSelected(true); trackedFilterBtn.setState(config.tab2TrackedValue().ordinal()); trackedFilterBtn.setEnabled(!config.tab2TrackedLock()); completedFilterBtn.setState(config.tab2CompletedValue().ordinal()); @@ -254,7 +239,8 @@ public void refreshFilterButtonsFromConfig(int tab) ignoredFilterBtn.setEnabled(!config.tab2IgnoredLock()); actionAllFilterButtonsNoRefresh(); break; - case 3: + case TAB_THREE: + if(!tabThree.isSelected()) tabThree.setSelected(true); trackedFilterBtn.setState(config.tab3TrackedValue().ordinal()); trackedFilterBtn.setEnabled(!config.tab3TrackedLock()); completedFilterBtn.setState(config.tab3CompletedValue().ordinal()); diff --git a/src/main/java/net/reldo/taskstracker/panel/TasksTrackerPluginPanel.java b/src/main/java/net/reldo/taskstracker/panel/TasksTrackerPluginPanel.java index 04c2e88..53b0585 100644 --- a/src/main/java/net/reldo/taskstracker/panel/TasksTrackerPluginPanel.java +++ b/src/main/java/net/reldo/taskstracker/panel/TasksTrackerPluginPanel.java @@ -7,6 +7,7 @@ import lombok.extern.slf4j.Slf4j; import net.reldo.taskstracker.TasksTrackerConfig; import net.reldo.taskstracker.TasksTrackerPlugin; +import net.reldo.taskstracker.config.ConfigValues; import net.reldo.taskstracker.data.task.TaskFromStruct; import net.reldo.taskstracker.data.task.TaskService; import net.runelite.client.game.SpriteManager; @@ -64,7 +65,7 @@ public void refresh(TaskFromStruct task) } } - public void refreshFilterButtonsFromConfig(int tab) + public void refreshFilterButtonsFromConfig(ConfigValues.TaskListTabs tab) { if (loggedIn) { From cbb20ee80bb4ae112bd890a572404ec6c79f1bad Mon Sep 17 00:00:00 2001 From: James Shelton Date: Wed, 11 Dec 2024 20:50:40 +0000 Subject: [PATCH 06/10] Buffer task list panel and batch task panel redraws supersedes c1d536ab0434ab26c0484a5e794457b3421c63fd --- .../taskstracker/TasksTrackerConfig.java | 17 +- .../taskstracker/TasksTrackerPlugin.java | 9 +- .../taskstracker/panel/LoggedInPanel.java | 13 +- .../reldo/taskstracker/panel/SortPanel.java | 10 +- .../taskstracker/panel/TaskListPanel.java | 203 ++++++++++++++---- .../panel/TasksTrackerPluginPanel.java | 9 + 6 files changed, 212 insertions(+), 49 deletions(-) diff --git a/src/main/java/net/reldo/taskstracker/TasksTrackerConfig.java b/src/main/java/net/reldo/taskstracker/TasksTrackerConfig.java index aa633b8..b5d1b5a 100644 --- a/src/main/java/net/reldo/taskstracker/TasksTrackerConfig.java +++ b/src/main/java/net/reldo/taskstracker/TasksTrackerConfig.java @@ -5,6 +5,7 @@ import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; import net.runelite.client.config.ConfigSection; +import net.runelite.client.config.Range; @ConfigGroup(TasksTrackerPlugin.CONFIG_GROUP_NAME) public interface TasksTrackerConfig extends Config @@ -50,13 +51,27 @@ default boolean filterPanelCollapsible() keyName = "saveSubFilterState", //@todo generalise this to all sub-filters name = "Save Filter State", description = "Configures whether the state of area filters should be saved and recalled when switching task type or restarting the plugin.", - hidden = true + hidden = true //todo This is hidden because it currently doesn't do anything ) default boolean saveSubFilterState() { return true; } + @Range( + min = 10 + ) + @ConfigItem( + position = 13, + keyName = "taskPanelBatchSize", + name = "Task Panel Batch Size", + description = "Configures the number of task panels to create in each batch when redrawing the task list panel." + ) + default int taskPanelBatchSize() + { + return 20; + } + @ConfigItem( position = 100, keyName = "completedFilter", diff --git a/src/main/java/net/reldo/taskstracker/TasksTrackerPlugin.java b/src/main/java/net/reldo/taskstracker/TasksTrackerPlugin.java index 0c163de..f2d9278 100644 --- a/src/main/java/net/reldo/taskstracker/TasksTrackerPlugin.java +++ b/src/main/java/net/reldo/taskstracker/TasksTrackerPlugin.java @@ -225,6 +225,11 @@ public void onConfigChanged(ConfigChanged configChanged) pluginPanel.refreshFilterButtonsFromConfig(config.taskListTab()); refresh(); } + + if (configChanged.getKey().equals("taskPanelBatchSize")) + { + pluginPanel.taskListPanel.setBatchSize(config.taskPanelBatchSize()); + } } @Subscribe @@ -263,7 +268,7 @@ public void onGameTick(GameTick gameTick) log.debug("forceUpdateVarpsFlag game tick"); trackerConfigStore.loadCurrentTaskTypeFromConfig(); forceVarpUpdate(); - SwingUtilities.invokeLater(() -> pluginPanel.redraw()); + SwingUtilities.invokeLater(() -> pluginPanel.drawNewTaskType()); forceUpdateVarpsFlag = false; taskService.setTaskTypeChanged(false); } @@ -344,7 +349,7 @@ public void reloadTaskType() } SwingUtilities.invokeLater(() -> { - pluginPanel.redraw(); + pluginPanel.drawNewTaskType(); pluginPanel.refreshFilterButtonsFromConfig(config.taskListTab()); pluginPanel.refresh(null); }); diff --git a/src/main/java/net/reldo/taskstracker/panel/LoggedInPanel.java b/src/main/java/net/reldo/taskstracker/panel/LoggedInPanel.java index 66b8f00..180cd29 100644 --- a/src/main/java/net/reldo/taskstracker/panel/LoggedInPanel.java +++ b/src/main/java/net/reldo/taskstracker/panel/LoggedInPanel.java @@ -82,7 +82,7 @@ public Dimension getPreferredSize() return getParent().getSize(); } - public void redraw() + public void drawNewTaskType() { // taskTypeDropdown may become de-synced after profile change String selectedTaskTypeJsonName = taskTypeDropdown.getItemAt(taskTypeDropdown.getSelectedIndex()).getValue().getTaskJsonName(); @@ -100,6 +100,16 @@ public void redraw() } } } + + subFilterPanel.redraw(); + sortPanel.redraw(); + updateCollapseButtonText(); + + taskListPanel.drawNewTaskType(); + } + + public void redraw() + { subFilterPanel.redraw(); sortPanel.redraw(); updateCollapseButtonText(); @@ -335,7 +345,6 @@ private JPanel getNorthPanel() boolean wasTaskTypeChanged = taskService.setTaskType(taskType); if (wasTaskTypeChanged) { - redraw(); refresh(null); } }); diff --git a/src/main/java/net/reldo/taskstracker/panel/SortPanel.java b/src/main/java/net/reldo/taskstracker/panel/SortPanel.java index 76db7c4..30cc1bf 100644 --- a/src/main/java/net/reldo/taskstracker/panel/SortPanel.java +++ b/src/main/java/net/reldo/taskstracker/panel/SortPanel.java @@ -56,10 +56,7 @@ public void redraw() sortDropdown.setSelectedIndex(0); sortDropdown.addActionListener(e -> { updateConfig(); - SwingUtilities.invokeLater(() -> { - taskListPanel.redraw(); - taskListPanel.refresh(null); - }); + SwingUtilities.invokeLater(taskListPanel::redraw); }); sortDropdown.setFocusable(false); @@ -70,10 +67,7 @@ public void redraw() directionButton.setBackground(ColorScheme.DARK_GRAY_COLOR); directionButton.setStateChangedAction(e -> { updateConfig(); - SwingUtilities.invokeLater(() -> { - taskListPanel.redraw(); - taskListPanel.refresh(null); - }); + SwingUtilities.invokeLater(taskListPanel::redraw); }); add(sortDropdown); diff --git a/src/main/java/net/reldo/taskstracker/panel/TaskListPanel.java b/src/main/java/net/reldo/taskstracker/panel/TaskListPanel.java index 10ebb54..251543e 100644 --- a/src/main/java/net/reldo/taskstracker/panel/TaskListPanel.java +++ b/src/main/java/net/reldo/taskstracker/panel/TaskListPanel.java @@ -4,12 +4,14 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.function.IntConsumer; import javax.swing.BoxLayout; import javax.swing.JLabel; import javax.swing.JScrollPane; import javax.swing.ScrollPaneConstants; import javax.swing.SwingUtilities; import javax.swing.border.EmptyBorder; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import net.reldo.taskstracker.TasksTrackerPlugin; import net.reldo.taskstracker.config.ConfigValues; @@ -24,30 +26,78 @@ public class TaskListPanel extends JScrollPane { public TasksTrackerPlugin plugin; - public final ArrayList taskPanels = new ArrayList<>(); - private final TaskListListPanel taskList; + private final int TASK_LIST_BUFFER_COUNT = 2; + public ArrayList taskPanels = new ArrayList<>(); //todo check if this should be final + private final ArrayList taskListBuffers = new ArrayList<>(TASK_LIST_BUFFER_COUNT); + private int currentTaskListBufferIndex; private final TaskService taskService; private final JLabel emptyTasks = new JLabel(); + @Setter + private int batchSize; public TaskListPanel(TasksTrackerPlugin plugin, TaskService taskService) { this.plugin = plugin; - - taskList = new TaskListListPanel(plugin); this.taskService = taskService; + batchSize = plugin.getConfig().taskPanelBatchSize(); + + FixedWidthPanel taskListListPanelWrapper = new FixedWidthPanel(); + + for(int i = 0; i < TASK_LIST_BUFFER_COUNT; i++) + { + taskListBuffers.add(new TaskListListPanel(plugin)); + taskListListPanelWrapper.add(taskListBuffers.get(i)); + } - setViewportView(taskList); + setViewportView(taskListListPanelWrapper); setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + + setCurrentTaskListListPanel(0); } - public String getEmptyTaskListMessage() + private void setCurrentTaskListListPanel(int index) { - return "No tasks match the current filters."; + if (index != currentTaskListBufferIndex) + { + taskListBuffers.get(currentTaskListBufferIndex).setVisible(false); + taskListBuffers.get(index).setVisible(true); + currentTaskListBufferIndex = index; + } + } + + private TaskListListPanel getCurrentTaskListListPanel() + { + return taskListBuffers.get(currentTaskListBufferIndex); + } + + private TaskListListPanel getNextTaskListListPanel() + { + return taskListBuffers.get(getNextBufferIndex()); + } + + private void showNextTaskListListPanel() + { + log.info("Showing next task list list panel: {}", getNextBufferIndex()); + TaskListListPanel previousPanel = getCurrentTaskListListPanel(); + setCurrentTaskListListPanel(getNextBufferIndex()); + previousPanel.prepEmptyTaskListPanel(); + } + + private int getNextBufferIndex() + { + return (currentTaskListBufferIndex + 1) % TASK_LIST_BUFFER_COUNT; + } + + public void drawNewTaskType() + { + log.info("Drawing new Task Type taskListListPanel"); + getNextTaskListListPanel().drawNewTaskType(); } public void redraw() { - taskList.redraw(); + log.info("Redrawing taskListListPanel"); + getNextTaskListListPanel().redraw(); } public void refresh(TaskFromStruct task) @@ -91,25 +141,30 @@ public void refreshTaskPanelsWithSkill(Skill skill) // Refresh all task panels for tasks with 'skill' or // 'SKILLS' (any skill) or 'TOTAL LEVEL' as a requirement. taskPanels.stream() - .filter(tp -> + .filter(tp -> + { + List skillsList = tp.task.getTaskDefinition().getSkills(); + if(skillsList == null || skillsList.isEmpty()) { - List skillsList = tp.task.getTaskDefinition().getSkills(); - if(skillsList == null || skillsList.isEmpty()) - { - return false; - } - - return skillsList.stream() - .map(TaskDefinitionSkill::getSkill) - .anyMatch(s -> s.equalsIgnoreCase(skill.getName()) || - s.equalsIgnoreCase("SKILLS") || - s.equalsIgnoreCase("TOTAL LEVEL") - ); - }) - .forEach(TaskPanel::refresh); + return false; + } + + return skillsList.stream() + .map(TaskDefinitionSkill::getSkill) + .anyMatch(s -> s.equalsIgnoreCase(skill.getName()) || + s.equalsIgnoreCase("SKILLS") || + s.equalsIgnoreCase("TOTAL LEVEL") + ); + }) + .forEach(TaskPanel::refresh); } - private class TaskListListPanel extends FixedWidthPanel + public String getEmptyTaskListMessage() + { + return "No tasks match the current filters."; + } + + private class TaskListListPanel extends FixedWidthPanel { private final TasksTrackerPlugin plugin; @@ -130,16 +185,21 @@ public TaskListListPanel(TasksTrackerPlugin plugin) emptyTasks.setVisible(false); } - public void redraw() + public void prepEmptyTaskListPanel() { - log.debug("TaskListPanel.redraw"); - if(SwingUtilities.isEventDispatchThread()) + SwingUtilities.invokeLater(() -> { removeAll(); - taskPanels.clear(); add(emptyTasks); emptyTasks.setVisible(false); + }); + } + public void drawNewTaskType() + { + log.debug("TaskListPanel.drawNewTaskType"); + if(SwingUtilities.isEventDispatchThread()) + { log.debug("TaskListPanel creating panels"); List tasks = taskService.getTasks(); if (tasks == null || tasks.isEmpty()) @@ -148,24 +208,95 @@ public void redraw() return; } - for (int indexPosition = 0; indexPosition < tasks.size(); indexPosition++) + // Buffer to hold newly created task panels before they are swapped in + ArrayList newTaskPanels = new ArrayList<>(tasks.size()); + + processInBatches(tasks.size(), indexPosition -> + { + TaskPanel taskPanel = new TaskPanel(plugin, tasks.get(indexPosition)); + add(taskPanel); + newTaskPanels.add(taskPanel); + if (indexPosition == (batchSize - 1)) taskPanels = newTaskPanels; // replace taskPanels list at end of first batch + }); + + SwingUtilities.invokeLater(() -> refresh(null)); + } + else + { + log.error("Task list panel drawNewTaskType failed - not event dispatch thread."); + } + } + + public void redraw() + { + log.debug("TaskListPanel.redraw"); + if(SwingUtilities.isEventDispatchThread()) + { + log.debug("TaskListPanel adding panels"); + if (taskPanels == null || taskPanels.isEmpty()) + { + emptyTasks.setVisible(true); + return; + } + + processInBatches(taskPanels.size(), indexPosition -> { int adjustedIndexPosition = indexPosition; if (plugin.getConfig().sortDirection().equals(ConfigValues.SortDirections.DESCENDING)) - adjustedIndexPosition = tasks.size() - (adjustedIndexPosition + 1); - TaskPanel taskPanel = new TaskPanel(plugin, tasks.get(taskService.getSortedTaskIndex(plugin.getConfig().sortCriteria(), adjustedIndexPosition))); + adjustedIndexPosition = taskPanels.size() - (adjustedIndexPosition + 1); + TaskPanel taskPanel = taskPanels.get(taskService.getSortedTaskIndex(plugin.getConfig().sortCriteria(), adjustedIndexPosition)); add(taskPanel); - taskPanels.add(taskPanel); - } + }); - log.debug("TaskListPanel validate and repaint"); - validate(); - repaint(); + SwingUtilities.invokeLater(() -> refresh(null)); } else { log.error("Task list panel redraw failed - not event dispatch thread."); } } + + private void processInBatches(int objectCount, IntConsumer method) + { + log.debug("TaskListPanel.processInBatches"); + + int numberOfBatches = (objectCount / batchSize) + 1; + + for(int batch = 0; batch < numberOfBatches; batch++) + { + if(batch == 0) + { + processBatch(batch, objectCount, method); + showNextTaskListListPanel(); + } + else + { + int batchIndex = batch; // lambda parameter should be effectively final + SwingUtilities.invokeLater(() -> processBatch(batchIndex, objectCount, method)); + } + } + } + + private void processBatch(int batch, int objectCount, IntConsumer method) + { + log.debug("TaskListPanel.processBatch"); + + for (int index = 0; index < batchSize; index++) + { + int indexPosition = index + (batch * batchSize); + if (indexPosition < objectCount) + { + method.accept(indexPosition); + } + else + { + break; + } + } + + log.debug("TaskListPanel validate and repaint after batch {}", batch); + validate(); + repaint(); + } } } diff --git a/src/main/java/net/reldo/taskstracker/panel/TasksTrackerPluginPanel.java b/src/main/java/net/reldo/taskstracker/panel/TasksTrackerPluginPanel.java index 53b0585..a52eaa6 100644 --- a/src/main/java/net/reldo/taskstracker/panel/TasksTrackerPluginPanel.java +++ b/src/main/java/net/reldo/taskstracker/panel/TasksTrackerPluginPanel.java @@ -100,4 +100,13 @@ public void setLoggedIn(boolean loggedIn) log.error("Failed to update loggedIn state - not event dispatch thread."); } } + + public void drawNewTaskType() + { + if (loggedIn) + { + loggedInPanel.drawNewTaskType(); + } + + } } \ No newline at end of file From af94449fdc4bc4d502b3538adfe1687eff9a23e6 Mon Sep 17 00:00:00 2001 From: James Shelton Date: Wed, 11 Dec 2024 21:20:30 +0000 Subject: [PATCH 07/10] Queue each task panel batch from the previous --- .../taskstracker/panel/TaskListPanel.java | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/main/java/net/reldo/taskstracker/panel/TaskListPanel.java b/src/main/java/net/reldo/taskstracker/panel/TaskListPanel.java index 251543e..7264ab2 100644 --- a/src/main/java/net/reldo/taskstracker/panel/TaskListPanel.java +++ b/src/main/java/net/reldo/taskstracker/panel/TaskListPanel.java @@ -260,26 +260,13 @@ private void processInBatches(int objectCount, IntConsumer method) { log.debug("TaskListPanel.processInBatches"); - int numberOfBatches = (objectCount / batchSize) + 1; - - for(int batch = 0; batch < numberOfBatches; batch++) - { - if(batch == 0) - { - processBatch(batch, objectCount, method); - showNextTaskListListPanel(); - } - else - { - int batchIndex = batch; // lambda parameter should be effectively final - SwingUtilities.invokeLater(() -> processBatch(batchIndex, objectCount, method)); - } - } + processBatch(0, objectCount, method); + showNextTaskListListPanel(); } private void processBatch(int batch, int objectCount, IntConsumer method) { - log.debug("TaskListPanel.processBatch"); + log.info("TaskListPanel.processBatch {}", batch); for (int index = 0; index < batchSize; index++) { @@ -297,6 +284,13 @@ private void processBatch(int batch, int objectCount, IntConsumer method) log.debug("TaskListPanel validate and repaint after batch {}", batch); validate(); repaint(); + + // queue next batch if not done + int batchIndex = batch + 1; + if (batchIndex * batchSize < objectCount) + { + SwingUtilities.invokeLater(() -> processBatch(batchIndex, objectCount, method)); + } } } } From 0ebf63ca9a85f52078e6601fd25002bde1c94b40 Mon Sep 17 00:00:00 2001 From: James Shelton Date: Wed, 11 Dec 2024 22:04:40 +0000 Subject: [PATCH 08/10] Use setComponentZOrder on task list redraw --- .../taskstracker/panel/TaskListPanel.java | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/main/java/net/reldo/taskstracker/panel/TaskListPanel.java b/src/main/java/net/reldo/taskstracker/panel/TaskListPanel.java index 7264ab2..9d548c3 100644 --- a/src/main/java/net/reldo/taskstracker/panel/TaskListPanel.java +++ b/src/main/java/net/reldo/taskstracker/panel/TaskListPanel.java @@ -27,7 +27,7 @@ public class TaskListPanel extends JScrollPane { public TasksTrackerPlugin plugin; private final int TASK_LIST_BUFFER_COUNT = 2; - public ArrayList taskPanels = new ArrayList<>(); //todo check if this should be final + public ArrayList taskPanels = new ArrayList<>(); private final ArrayList taskListBuffers = new ArrayList<>(TASK_LIST_BUFFER_COUNT); private int currentTaskListBufferIndex; private final TaskService taskService; @@ -77,7 +77,7 @@ private TaskListListPanel getNextTaskListListPanel() private void showNextTaskListListPanel() { - log.info("Showing next task list list panel: {}", getNextBufferIndex()); + log.debug("Showing next task list list panel: {}", getNextBufferIndex()); TaskListListPanel previousPanel = getCurrentTaskListListPanel(); setCurrentTaskListListPanel(getNextBufferIndex()); previousPanel.prepEmptyTaskListPanel(); @@ -90,14 +90,14 @@ private int getNextBufferIndex() public void drawNewTaskType() { - log.info("Drawing new Task Type taskListListPanel"); + log.debug("Drawing new Task Type taskListListPanel"); getNextTaskListListPanel().drawNewTaskType(); } public void redraw() { - log.info("Redrawing taskListListPanel"); - getNextTaskListListPanel().redraw(); + log.debug("Redrawing taskListListPanel"); + getCurrentTaskListListPanel().redraw(); } public void refresh(TaskFromStruct task) @@ -232,21 +232,20 @@ public void redraw() log.debug("TaskListPanel.redraw"); if(SwingUtilities.isEventDispatchThread()) { - log.debug("TaskListPanel adding panels"); if (taskPanels == null || taskPanels.isEmpty()) { emptyTasks.setVisible(true); return; } - processInBatches(taskPanels.size(), indexPosition -> + for (int indexPosition = 0; indexPosition < taskPanels.size(); indexPosition++) { int adjustedIndexPosition = indexPosition; if (plugin.getConfig().sortDirection().equals(ConfigValues.SortDirections.DESCENDING)) adjustedIndexPosition = taskPanels.size() - (adjustedIndexPosition + 1); TaskPanel taskPanel = taskPanels.get(taskService.getSortedTaskIndex(plugin.getConfig().sortCriteria(), adjustedIndexPosition)); - add(taskPanel); - }); + setComponentZOrder(taskPanel, indexPosition); + } SwingUtilities.invokeLater(() -> refresh(null)); } @@ -258,15 +257,13 @@ public void redraw() private void processInBatches(int objectCount, IntConsumer method) { - log.debug("TaskListPanel.processInBatches"); - processBatch(0, objectCount, method); showNextTaskListListPanel(); } private void processBatch(int batch, int objectCount, IntConsumer method) { - log.info("TaskListPanel.processBatch {}", batch); + log.debug("TaskListPanel.processBatch {}", batch); for (int index = 0; index < batchSize; index++) { @@ -281,7 +278,6 @@ private void processBatch(int batch, int objectCount, IntConsumer method) } } - log.debug("TaskListPanel validate and repaint after batch {}", batch); validate(); repaint(); From 44079c800a66f059c7e19e5d4c9de61006346bc3 Mon Sep 17 00:00:00 2001 From: James Shelton Date: Mon, 16 Dec 2024 20:33:58 +0000 Subject: [PATCH 09/10] Fix plugin panel initialisation and update default config --- .../taskstracker/TasksTrackerConfig.java | 28 +++++++++++++------ .../net/reldo/taskstracker/panel/Icons.java | 6 ++-- .../taskstracker/panel/LoggedInPanel.java | 19 ++----------- .../taskstracker/panel/TaskListPanel.java | 20 +++++++------ 4 files changed, 35 insertions(+), 38 deletions(-) diff --git a/src/main/java/net/reldo/taskstracker/TasksTrackerConfig.java b/src/main/java/net/reldo/taskstracker/TasksTrackerConfig.java index b5d1b5a..e7a2831 100644 --- a/src/main/java/net/reldo/taskstracker/TasksTrackerConfig.java +++ b/src/main/java/net/reldo/taskstracker/TasksTrackerConfig.java @@ -58,6 +58,15 @@ default boolean saveSubFilterState() return true; } + + @ConfigSection( + name = "Internal Config", + description = "These settings change the internal behaviour of the plugin. Reset them if any issues occur.", + position = 10, + closedByDefault = true + ) + String internalConfig = "internalConfig"; + @Range( min = 10 ) @@ -65,11 +74,12 @@ default boolean saveSubFilterState() position = 13, keyName = "taskPanelBatchSize", name = "Task Panel Batch Size", - description = "Configures the number of task panels to create in each batch when redrawing the task list panel." + description = "Configures the number of task panels to create in each batch when redrawing the task list panel.", + section = internalConfig ) default int taskPanelBatchSize() { - return 20; + return 50; } @ConfigItem( @@ -192,7 +202,7 @@ default ConfigValues.SortDirections sortDirection() ) default String tab1Name() { - return "Tracked Tasks"; + return "Tracked"; } @ConfigItem( @@ -216,7 +226,7 @@ default boolean tab1CompletedLock() ) default ConfigValues.CompletedFilterValues tab1CompletedValue() { - return ConfigValues.CompletedFilterValues.COMPLETE_AND_INCOMPLETE; + return ConfigValues.CompletedFilterValues.INCOMPLETE; } @ConfigItem( @@ -287,7 +297,7 @@ default ConfigValues.IgnoredFilterValues tab1IgnoredValue() ) default String tab2Name() { - return "All Tasks"; + return "Incomplete"; } @ConfigItem( @@ -311,7 +321,7 @@ default boolean tab2CompletedLock() ) default ConfigValues.CompletedFilterValues tab2CompletedValue() { - return ConfigValues.CompletedFilterValues.COMPLETE_AND_INCOMPLETE; + return ConfigValues.CompletedFilterValues.INCOMPLETE; } @ConfigItem( @@ -359,7 +369,7 @@ default boolean tab2IgnoredLock() ) default ConfigValues.IgnoredFilterValues tab2IgnoredValue() { - return ConfigValues.IgnoredFilterValues.IGNORED_AND_NOT_IGNORED; + return ConfigValues.IgnoredFilterValues.NOT_IGNORED; } /*================== @@ -382,7 +392,7 @@ default ConfigValues.IgnoredFilterValues tab2IgnoredValue() ) default String tab3Name() { - return "Custom"; + return "All Tasks"; } @ConfigItem( @@ -454,7 +464,7 @@ default boolean tab3IgnoredLock() ) default ConfigValues.IgnoredFilterValues tab3IgnoredValue() { - return ConfigValues.IgnoredFilterValues.NOT_IGNORED; + return ConfigValues.IgnoredFilterValues.IGNORED_AND_NOT_IGNORED; } diff --git a/src/main/java/net/reldo/taskstracker/panel/Icons.java b/src/main/java/net/reldo/taskstracker/panel/Icons.java index c8e90a0..707d7f7 100644 --- a/src/main/java/net/reldo/taskstracker/panel/Icons.java +++ b/src/main/java/net/reldo/taskstracker/panel/Icons.java @@ -15,9 +15,9 @@ public class Icons private static final String ignoredBtnPath = "panel/components/ignored_button/"; public static final BufferedImage semivisibleimg = ImageUtil.loadImageResource(TasksTrackerPlugin.class, ignoredBtnPath + "semivisible_icon.png"); - public static final Icon SEMIVISIBLE_ICON = new ImageIcon(ImageUtil.alphaOffset(semivisibleimg, -180)); - public static final Icon INVISIBLE_ICON = new ImageIcon(ImageUtil.loadImageResource(TasksTrackerPlugin.class, ignoredBtnPath + "invisible_icon.png")); - public static final Icon VISIBLE_ICON = new ImageIcon(ImageUtil.loadImageResource(TasksTrackerPlugin.class, ignoredBtnPath + "visible_icon.png")); + public static final Icon UNIGNORED_ONLY_ICON = new ImageIcon(ImageUtil.alphaOffset(semivisibleimg, -180)); + public static final Icon IGNORED_ONLY_ICON = new ImageIcon(ImageUtil.loadImageResource(TasksTrackerPlugin.class, ignoredBtnPath + "invisible_icon.png")); + public static final Icon IGNORED_UNIGNORED_ICON = new ImageIcon(ImageUtil.loadImageResource(TasksTrackerPlugin.class, ignoredBtnPath + "visible_icon.png")); private static final String trackedBtnPath = "panel/components/tracked_button/"; public static final Icon UNTRACKED_ONLY_ICON = new ImageIcon(ImageUtil.loadImageResource(TasksTrackerPlugin.class, trackedBtnPath + "untracked_icon.png")); diff --git a/src/main/java/net/reldo/taskstracker/panel/LoggedInPanel.java b/src/main/java/net/reldo/taskstracker/panel/LoggedInPanel.java index 180cd29..51403c8 100644 --- a/src/main/java/net/reldo/taskstracker/panel/LoggedInPanel.java +++ b/src/main/java/net/reldo/taskstracker/panel/LoggedInPanel.java @@ -5,8 +5,6 @@ import java.awt.Dimension; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; import java.util.Optional; import javax.swing.Box; import javax.swing.BoxLayout; @@ -106,6 +104,7 @@ public void drawNewTaskType() updateCollapseButtonText(); taskListPanel.drawNewTaskType(); + refreshFilterButtonsFromConfig(config.taskListTab()); } public void redraw() @@ -171,20 +170,6 @@ private JPanel getCenterPanel() { taskListPanel.add(tabPane, BorderLayout.NORTH); taskListPanel.add(this.taskListPanel, BorderLayout.CENTER); - switch (config.taskListTab()) - { - case TAB_ONE: - tabOne.setSelected(true); - break; - case TAB_TWO: - tabTwo.setSelected(true); - break; - case TAB_THREE: - tabThree.setSelected(true); - break; - } - tabChanged(config.taskListTab()); - return taskListPanel; } @@ -441,7 +426,7 @@ private JPanel getTitleAndButtonPanel() // Ignored tasks filter button SwingUtil.removeButtonDecorations(ignoredFilterBtn); - ignoredFilterBtn.setIcons(Icons.SEMIVISIBLE_ICON, Icons.VISIBLE_ICON, Icons.INVISIBLE_ICON); + ignoredFilterBtn.setIcons(Icons.UNIGNORED_ONLY_ICON, Icons.IGNORED_UNIGNORED_ICON, Icons.IGNORED_ONLY_ICON); ignoredFilterBtn.setToolTips("Hide ignored tasks", "All tasks", "Ignored tasks only"); ignoredFilterBtn.setBackground(ColorScheme.DARK_GRAY_COLOR); ignoredFilterBtn.setStateChangedAction(e -> filterButtonAction("ignored")); diff --git a/src/main/java/net/reldo/taskstracker/panel/TaskListPanel.java b/src/main/java/net/reldo/taskstracker/panel/TaskListPanel.java index 9d548c3..aa88529 100644 --- a/src/main/java/net/reldo/taskstracker/panel/TaskListPanel.java +++ b/src/main/java/net/reldo/taskstracker/panel/TaskListPanel.java @@ -187,12 +187,7 @@ public TaskListListPanel(TasksTrackerPlugin plugin) public void prepEmptyTaskListPanel() { - SwingUtilities.invokeLater(() -> - { - removeAll(); - add(emptyTasks); - emptyTasks.setVisible(false); - }); + SwingUtilities.invokeLater(this::removeAll); } public void drawNewTaskType() @@ -201,6 +196,9 @@ public void drawNewTaskType() if(SwingUtilities.isEventDispatchThread()) { log.debug("TaskListPanel creating panels"); + + add(emptyTasks); + List tasks = taskService.getTasks(); if (tasks == null || tasks.isEmpty()) { @@ -208,6 +206,8 @@ public void drawNewTaskType() return; } + emptyTasks.setVisible(false); + // Buffer to hold newly created task panels before they are swapped in ArrayList newTaskPanels = new ArrayList<>(tasks.size()); @@ -218,8 +218,6 @@ public void drawNewTaskType() newTaskPanels.add(taskPanel); if (indexPosition == (batchSize - 1)) taskPanels = newTaskPanels; // replace taskPanels list at end of first batch }); - - SwingUtilities.invokeLater(() -> refresh(null)); } else { @@ -281,12 +279,16 @@ private void processBatch(int batch, int objectCount, IntConsumer method) validate(); repaint(); - // queue next batch if not done + // queue next batch if not done or refresh after last batch int batchIndex = batch + 1; if (batchIndex * batchSize < objectCount) { SwingUtilities.invokeLater(() -> processBatch(batchIndex, objectCount, method)); } + else + { + SwingUtilities.invokeLater(() -> refresh(null)); + } } } } From 94f4f708a69ed6a847d98a90879a7ad1c3e9880f Mon Sep 17 00:00:00 2001 From: James Shelton Date: Mon, 16 Dec 2024 21:29:49 +0000 Subject: [PATCH 10/10] Refresh empty task list panel message each batch --- .../taskstracker/panel/TaskListPanel.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/main/java/net/reldo/taskstracker/panel/TaskListPanel.java b/src/main/java/net/reldo/taskstracker/panel/TaskListPanel.java index aa88529..aee7bbe 100644 --- a/src/main/java/net/reldo/taskstracker/panel/TaskListPanel.java +++ b/src/main/java/net/reldo/taskstracker/panel/TaskListPanel.java @@ -121,14 +121,7 @@ public void refresh(TaskFromStruct task) } } - Optional visibleTaskPanel = taskPanels.stream() - .filter(TaskPanel::isVisible) - .findFirst(); - - if (visibleTaskPanel.isEmpty()) - { - emptyTasks.setVisible(true); - } + refreshEmptyPanel(); } else { @@ -136,6 +129,18 @@ public void refresh(TaskFromStruct task) } } + private void refreshEmptyPanel() + { + Optional visibleTaskPanel = taskPanels.stream() + .filter(TaskPanel::isVisible) + .findFirst(); + + if (visibleTaskPanel.isEmpty()) + { + emptyTasks.setVisible(true); + } + } + public void refreshTaskPanelsWithSkill(Skill skill) { // Refresh all task panels for tasks with 'skill' or @@ -276,6 +281,7 @@ private void processBatch(int batch, int objectCount, IntConsumer method) } } + refreshEmptyPanel(); validate(); repaint();