ScratchPad Plugin: cleanup and refactor

This commit is contained in:
Sergey Ponomarev
2026-03-19 18:24:02 +02:00
parent 031c7a015f
commit ead1110f4a
5 changed files with 100 additions and 240 deletions

View File

@ -15,8 +15,7 @@
*/
package org.jivesoftware.sparkimpl.plugin.scratchpad;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.iqprivate.PrivateDataManager;
@ -32,6 +31,8 @@ import java.io.IOException;
* @author Derek DeMoro
*/
public class PrivateNotes implements PrivateData {
public static final String ELEMENT = "scratchpad";
public static final String NAMESPACE = "scratchpad:notes";
private String notes;
@ -43,47 +44,26 @@ public class PrivateNotes implements PrivateData {
}
public void setNotes(String notes) {
if (notes != null) {
this.notes = notes.replaceAll("&", "&");
} else {
this.notes = notes;
}
}
public void setMyNotes(String notes) {
this.notes = notes;
}
/**
* Returns the root element name.
*/
@Override
public String getElementName() {
return "scratchpad";
return ELEMENT;
}
/**
* Returns the root element XML namespace.
*/
@Override
public String getNamespace() {
return "scratchpad:notes";
return NAMESPACE;
}
/**
* Returns the XML representation of the PrivateData.
*/
@Override
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<scratchpad xmlns=\"scratchpad:notes\">");
if (getNotes() != null) {
buf.append("<text>").append(getNotes()).append("</text>");
}
buf.append("</scratchpad>");
return buf.toString();
public XmlStringBuilder toXML() {
XmlStringBuilder buf = new XmlStringBuilder();
buf.halfOpenElement(ELEMENT).xmlnsAttribute(NAMESPACE).rightAngleBracket();
buf.optElement("text", getNotes());
buf.closeElement(ELEMENT);
return buf;
}
/**
@ -104,7 +84,7 @@ public class PrivateNotes implements PrivateData {
if (eventType == XmlPullParser.Event.START_ELEMENT && "text".equals(parser.getName())) {
notes.setNotes(parser.nextText());
} else if (eventType == XmlPullParser.Event.END_ELEMENT) {
if ("scratchpad".equals(parser.getName())) {
if (ELEMENT.equals(parser.getName())) {
done = true;
}
}
@ -113,33 +93,28 @@ public class PrivateNotes implements PrivateData {
}
}
static {
PrivateDataManager.addPrivateDataProvider(ELEMENT, NAMESPACE, new PrivateNotes.Provider());
}
public static void savePrivateNotes(PrivateNotes notes) {
PrivateDataManager manager = SparkManager.getSessionManager().getPersonalDataManager();
PrivateDataManager.addPrivateDataProvider("scratchpad", "scratchpad:notes", new PrivateNotes.Provider());
try {
manager.setPrivateData(notes);
} catch (XMPPException | SmackException | InterruptedException e) {
} catch (Exception e) {
Log.error(e);
throw new RuntimeException(e.getMessage());
}
}
public static PrivateNotes getPrivateNotes() {
PrivateDataManager manager = SparkManager.getSessionManager().getPersonalDataManager();
PrivateDataManager.addPrivateDataProvider("scratchpad", "scratchpad:notes", new PrivateNotes.Provider());
PrivateNotes notes = null;
try {
notes = (PrivateNotes) manager.getPrivateData("scratchpad", "scratchpad:notes");
} catch (XMPPException | SmackException | InterruptedException e) {
PrivateData privateData = manager.getPrivateData(ELEMENT, NAMESPACE);
return privateData != null ? (PrivateNotes) privateData : new PrivateNotes();
} catch (Exception e) {
Log.error(e);
throw new RuntimeException(e.getMessage());
}
if (notes.getNotes() != null) {
String note = notes.getNotes().replaceAll("&amp;", "&");
notes.setMyNotes(note);
}
return notes;
}
}

View File

@ -56,7 +56,6 @@ public class ScratchPadPlugin implements Plugin {
@Override
public void initialize() {
TimerTask startTask = new TimerTask() {
@Override
public void run() {
@ -94,17 +93,6 @@ public class ScratchPadPlugin implements Plugin {
}
});
//TODO REMOVE
@SuppressWarnings("unused")
int index = -1;
JPanel commandPanel = SparkManager.getWorkspace().getCommandPanel();
for (int i = 0; i < commandPanel.getComponentCount(); i++) {
if (commandPanel.getComponent(i) instanceof JLabel) {
break;
}
}
JMenuItem taskMenu = new JMenuItem(Res.getString("button.view.tasklist"), SparkRes.getImageIcon(SparkRes.Icon.DESKTOP_IMAGE));
taskMenu.addActionListener(e -> showTaskList());
@ -123,7 +111,6 @@ public class ScratchPadPlugin implements Plugin {
// Start notifications.
new TaskNotification();
}
@ -133,8 +120,6 @@ public class ScratchPadPlugin implements Plugin {
panel_events.removeAll();
mainPanel.removeAll();
//final List<TaskUI> taskList = new ArrayList<TaskUI>();
//final JPanel mainPanel = new JPanel();
mainPanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false));
mainPanel.setBackground(Color.white);
@ -285,6 +270,7 @@ public class ScratchPadPlugin implements Plugin {
addButton.addActionListener(addAction);
Tasks tasks = Tasks.getTaskList();
SHOW_ALL_TASKS = tasks.isShowAll();
updateTaskUI(tasks);
if (SHOW_ALL_TASKS) {
@ -314,12 +300,13 @@ public class ScratchPadPlugin implements Plugin {
public void actionPerformed(ActionEvent actionEvent) {
// Save it.
Tasks tasks = new Tasks();
tasks.setShowAll(SHOW_ALL_TASKS);
for (TaskUI ui : taskList) {
Task task = ui.getTask();
tasks.addTask(task);
}
Tasks.saveTasks(tasks, SparkManager.getConnection());
Tasks.saveTasks(tasks);
}
};
@ -499,60 +486,4 @@ public class ScratchPadPlugin implements Plugin {
return taskList;
}
// private class DragWindowAdapter extends MouseAdapter
// implements MouseMotionListener {
// private JFrame m_msgWnd;
// private int m_mousePrevX,
// m_mousePrevY;
// private int m_frameX,
// m_frameY;
//
// public DragWindowAdapter(JFrame mw) {
// m_msgWnd = mw;
// }
//
// public void mousePressed(MouseEvent e) {
// super.mousePressed(e);
// m_mousePrevX = e.getX();
// m_mousePrevY = e.getY();
// m_frameX = 0;
// m_frameY = 0;
// }
//
// public void mouseDragged(MouseEvent e) {
// int X = e.getX();
// int Y = e.getY();
// int MsgX = m_msgWnd.getX();
// int MsgY = m_msgWnd.getY();
//
// int moveX = X - m_mousePrevX; // Negative if move left
// int moveY = Y - m_mousePrevY; // Negative if move down
// if (moveX == 0 && moveY == 0) return;
// m_mousePrevX = X - moveX;
// m_mousePrevY = Y - moveY;
//
// //System.out.println("mouseDragged x,y = (" + X + "," + Y +
// // ") diff (" + moveX + "," + moveY +
// // ") MsgX/MsgY = " + MsgX + "," + MsgY);
//
// // mouseDragged caused by setLocation() on frame.
// if (m_frameX == MsgX && m_frameY == MsgY) {
// m_frameX = 0;
// m_frameY = 0;
// return;
// }
//
// // '-' would cause wrong direction for movement.
// int newFrameX = MsgX + moveX;
// // '-' would cause wrong
// int newFrameY = MsgY + moveY;
//
// m_frameX = newFrameX;
// m_frameY = newFrameY;
// m_msgWnd.setLocation(newFrameX, newFrameY);
// }
//
// public void mouseMoved(MouseEvent e) {
// }
// }
}

View File

@ -24,7 +24,6 @@ import javax.swing.*;
import java.awt.*;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.Iterator;
import java.util.TimerTask;
import static java.time.ZoneId.*;
@ -62,13 +61,13 @@ public class TaskNotification {
mainPanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false));
mainPanel.setBackground(Color.white);
long now = System.currentTimeMillis();
Tasks tasks = Tasks.getTaskList();
if (tasks == null) {
return;
}
java.util.List<Task> tasksList = tasks.getTasks();
Iterator<Task> taskIter = tasksList.iterator();
long now = System.currentTimeMillis();
Tasks tasks;
try {
tasks = Tasks.getTaskList();
} catch (Exception ignored) {
return;
}
final JPanel titlePanel = new JPanel(new BorderLayout()) {
@Override
@ -93,8 +92,7 @@ public class TaskNotification {
mainPanel.add(titlePanel);
boolean hasItems = false;
while (taskIter.hasNext()) {
Task task = taskIter.next();
for (Task task : tasks.getTasks()) {
if (task.isCompleted()) {
continue;
}

View File

@ -20,8 +20,8 @@ import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.font.TextAttribute;
import java.text.SimpleDateFormat;
import java.util.Date;
@ -36,9 +36,8 @@ import org.jivesoftware.resource.SparkRes;
/**
*/
public class TaskUI extends JPanel implements ActionListener {
public class TaskUI extends JPanel {
private static final long serialVersionUID = -8443764502684168188L;
private final Task task;
private final JCheckBox box;
@ -77,7 +76,6 @@ public class TaskUI extends JPanel implements ActionListener {
}
int diff = DateUtils.getDaysDiff(dueDate, new Date().getTime());
if (diff > 0){
dueLabel.setForeground(Color.red);
}
@ -86,30 +84,21 @@ public class TaskUI extends JPanel implements ActionListener {
updateTitleFont();
box.addActionListener(this);
btn_del.addMouseListener(new MouseListener() {
box.addActionListener(e -> {
task.setCompleted(isSelected());
updateTitleFont();
if (ScratchPadPlugin.SHOW_ALL_TASKS) {
setVisible(true);
}
else if (task.isCompleted()) {
setVisible(false);
}
});
btn_del.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
Tasks.deleteTask(task);
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
});
}
@ -121,41 +110,19 @@ public class TaskUI extends JPanel implements ActionListener {
public void updateTitleFont() {
if (task.isCompleted()) {
Font font = box.getFont();
Map attribs = font.getAttributes();
Map attribs = font.getAttributes();
attribs.put(TextAttribute.STRIKETHROUGH, true);
box.setFont(new Font(attribs));
box.setSelected(true);
}
else {
} else {
Font font = box.getFont();
Map Attribs = font.getAttributes();
Map Attribs = font.getAttributes();
Attribs.put(TextAttribute.STRIKETHROUGH, false);
box.setFont(new Font(Attribs));
box.setSelected(false);
}
}
@Override
public void actionPerformed(ActionEvent e) {
task.setCompleted(isSelected());
updateTitleFont();
if (ScratchPadPlugin.SHOW_ALL_TASKS) {
setVisible(true);
}
else if (task.isCompleted()) {
setVisible(false);
}
}
public Task getTask() {
return task;
}

View File

@ -19,9 +19,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.iqprivate.PrivateDataManager;
@ -33,14 +31,14 @@ import org.jivesoftware.spark.util.log.Log;
import org.jxmpp.JxmppContext;
/**
* Tasks for a TO-DO list
* @author Derek DeMoro
*/
public class Tasks implements PrivateData {
public static final String ELEMENT = "scratchpad";
public static final String NAMESPACE = "scratchpad:tasks";
private List<Task> tasks = new ArrayList<>();
public Tasks() {
}
private boolean showAll;
public List<Task> getTasks() {
return tasks;
@ -54,46 +52,44 @@ public class Tasks implements PrivateData {
tasks.add(task);
}
/**
* Returns the root element name.
*/
public boolean isShowAll() {
return showAll;
}
public void setShowAll(boolean showAll) {
this.showAll = showAll;
}
@Override
public String getElementName() {
return "scratchpad";
return ELEMENT;
}
/**
* Returns the root element XML namespace.
*/
@Override
public String getNamespace() {
return "scratchpad:tasks";
return NAMESPACE;
}
/**
* Returns the XML representation of the PrivateData.
*/
@Override
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<scratchpad xmlns=\"scratchpad:tasks\">");
buf.append("<tasks showAll=\"").append(ScratchPadPlugin.SHOW_ALL_TASKS).append("\">");
public XmlStringBuilder toXML() {
XmlStringBuilder buf = new XmlStringBuilder();
buf.halfOpenElement(ELEMENT).xmlnsAttribute(NAMESPACE).rightAngleBracket();
buf.halfOpenElement("tasks");
buf.attribute("showAll", isShowAll());
buf.rightAngleBracket();
for (Task task : getTasks()) {
buf.append("<task>");
buf.append("<title>").append(task.getTitle()).append("</title>");
buf.append("<dueDate>").append(task.getDueDate()).append("</dueDate>");
buf.append("<creationDate>").append(task.getCreatedDate()).append("</creationDate>");
buf.openElement("task");
buf.optElement("title", task.getTitle());
buf.optElement("dueDate", task.getDueDate());
buf.optElement("creationDate", task.getCreatedDate());
if (task.isCompleted()) {
buf.append("<completed>true</completed>");
buf.optElement("completed", "true");
}
buf.append("</task>");
buf.closeElement("task");
}
buf.append("</tasks>");
buf.append("</scratchpad>");
return buf.toString();
buf.closeElement("tasks");
buf.closeElement(ELEMENT);
return buf;
}
/**
@ -113,15 +109,13 @@ public class Tasks implements PrivateData {
XmlPullParser.Event eventType = parser.next();
if (eventType == XmlPullParser.Event.START_ELEMENT && "tasks".equals(parser.getName())) {
String showAll = parser.getAttributeValue("", "showAll");
ScratchPadPlugin.SHOW_ALL_TASKS = Boolean.parseBoolean(showAll);
tasks.setShowAll(Boolean.parseBoolean(showAll));
}
if (eventType == XmlPullParser.Event.START_ELEMENT && "task".equals(parser.getName())) {
tasks.addTask(getTask(parser));
} else if (eventType == XmlPullParser.Event.END_ELEMENT) {
if ("scratchpad".equals(parser.getName())) {
done = true;
}
} else if (eventType == XmlPullParser.Event.END_ELEMENT && ELEMENT.equals(parser.getName())) {
done = true;
}
}
@ -154,10 +148,8 @@ public class Tasks implements PrivateData {
if (ModelUtil.hasLength(completed)) {
task.setCompleted(Boolean.parseBoolean(completed));
}
} else if (eventType == XmlPullParser.Event.END_ELEMENT) {
if ("task".equals(parser.getName())) {
done = true;
}
} else if (eventType == XmlPullParser.Event.END_ELEMENT && "task".equals(parser.getName())) {
done = true;
}
}
@ -165,43 +157,40 @@ public class Tasks implements PrivateData {
}
public static void saveTasks(Tasks tasks, XMPPConnection con) {
PrivateDataManager manager = SparkManager.getSessionManager().getPersonalDataManager();
PrivateDataManager.addPrivateDataProvider("scratchpad", "scratchpad:tasks", new Tasks.Provider());
try {
manager.setPrivateData(tasks);
} catch (XMPPException | SmackException | InterruptedException e) {
Log.error(e);
}
static {
PrivateDataManager.addPrivateDataProvider(ELEMENT, NAMESPACE, new Tasks.Provider());
}
static {
PrivateDataManager.addPrivateDataProvider("scratchpad", "scratchpad:tasks", new Tasks.Provider());
public static void saveTasks(Tasks tasks) {
PrivateDataManager manager = SparkManager.getSessionManager().getPersonalDataManager();
try {
manager.setPrivateData(tasks);
} catch (Exception e) {
Log.error(e);
throw new RuntimeException(e.getMessage());
}
}
public static Tasks getTaskList() {
PrivateDataManager manager = SparkManager.getSessionManager().getPersonalDataManager();
Tasks tasks = null;
try {
tasks = (Tasks) manager.getPrivateData("scratchpad", "scratchpad:tasks");
} catch (XMPPException | SmackException | InterruptedException e) {
PrivateData privateData = manager.getPrivateData(ELEMENT, NAMESPACE);
return privateData != null ? (Tasks) privateData : new Tasks();
} catch (Exception e) {
Log.error(e);
throw new RuntimeException(e.getMessage());
}
return tasks;
}
/**
* Delete task
*/
public static void deleteTask(Task task) {
public static void deleteTask(Task deletedTask) {
List<TaskUI> taskList = ScratchPadPlugin.getTaskList();
// find and delete task in list
for (int i = 0; i < taskList.size(); i++) {
Task t = taskList.get(i).getTask();
if (t == task) {
if (t == deletedTask) {
taskList.remove(i);
break;
}