JOSM 中自定义开发
在对JOSM 进行二次开发时的一些笔记,包含Action和Dialog 等。
Action
在JOSM 中可以通过在菜单栏中添加Action
来实现自定义功能。
// 忽略导包过程
public class AdjacentNodesAction extends JosmAction {
public static final boolean treeMode = false;
public AdjacentNodesAction() {
super(tr("名称"), // 在菜单栏中显示的名称
"图标名称", // 图标在resources/images 中
tr("提示信息"), // 注册快捷键
Shortcut.registerShortcut("主菜单名:名称","说明信息",
KeyEvent.VK_E, Shortcut.DIRECT), true); // 快捷键
putValue("help", ht("/Action/AdjacentNodes")); // 添加帮助信息
}
private transient Set<Way> activeWays = new HashSet<>();
@Override
public void actionPerformed(ActionEvent e) {
// action 执行的操作,重中之重
// 1. 通过曾管理器获取当前激活的数据集
DataSet ds = getLayerManager().getActiveDataSet();
// 2. 获取当前选中的元素,可以是点、路线或者是关系
Collection<Node> selectedNodes = ds.getSelectedNodes();
Set<Way> selectedWays = new LinkedHashSet<>(ds.getSelectedWays());
// 判断为空
if (selectedNodes.isEmpty() && selectedWays.isEmpty()) return;
if (selectedWays.isEmpty()) {
// 判断为空
} else {
activeWays = selectedWays;
}
// 随后可以对所选数据进行一系列操作,甚至是新增不存在的元素
// 如果需要创建对话框的话
LatLonDialog dialog = new LatLonDialog(MainApplication.getMainFrame(), tr("Add Node..."), ht("/Action/AddNode"));
dialog.showDialog(); // 在主窗口显示对话框,该操作会阻塞主界面
}
@Override
protected void updateEnabledState() {
// 所选层变化时更新
updateEnabledStateOnCurrentSelection();
}
@Override
protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
// 所选元素变化时更新,一般默认如下操作即可
// setEnabled(selection != null && !selection.isEmpty());
// 如果有暂存数据则需清空,如下:
boolean hasSel = selection != null && !selection.isEmpty();
if (!hasSel && activeWays != null) {
// 清空激活Ways
activeWays.clear();
}
setEnabled(hasSel);
}
}
定义对话框
public class LatLonDialog extends ExtendedDialog{
// ...
}
添加菜单项
定义完成后即可在MainMenu.java
中便可以新增元素:
public class MainMenu extends JMenuBar{
public void Initialize(){
// ...
selectionMenu.addSeparator();
add(selectionMenu, new SelectWayNodesAction());
// ...
}
}
可折叠对话框
public class MeasurementDialog extends ToggleDialog implements DataSelectionListener {
// 可以继承不只一个接口用于监听事件
public MeasurementDialog()
{
// 构造窗口,类似于Action
super(tr("测量数据"), "measure", tr("打开测量窗口"),
Shortcut.registerShortcut("subwindow:measurement", tr("窗口: {0}", tr("测量数据")),
KeyEvent.VK_U, Shortcut.CTRL_SHIFT), 150);
// 元素布局
// 添加事件监听
MainApplication.getLayerManager().addLayerChangeListener(this);
SelectionEventManager.getInstance().addSelectionListener(this);
SystemOfMeasurement.addSoMChangeListener(this);
}
@Override
public void selectionChanged(SelectionChangeEvent event) {
// 处理选中元素变化
refresh(event.getSelection());
}
@Override
public void destroy() {
// 析构函数,移除事件监听和其他资源
super.destroy();
SystemOfMeasurement.removeSoMChangeListener(this);
SelectionEventManager.getInstance().removeSelectionListener(this);
MainApplication.getLayerManager().removeLayerChangeListener(this);
}
// 按需重写各类监听
// @Override public void nodeMoved(NodeMovedEvent event) { }
// ...
}
可以在MainFrame.java
中注册使用:
public class MapFrame extends JPanel implements Destroyable, ActiveLayerChangeListener, LayerChangeListener {
public MapFrame(ViewportData viewportData) {
// ...
measurementDialog = new MeasurementDialog();
addToggleDialog(measurementDialog);
// ...
}
}