User:DressyPear4/PintarNotas

From OpenStreetMap Wiki
Jump to navigation Jump to search

Pintar notas selecionadas

Um script para apoio ao plugin NoteSolver. Com esse código você pode destacar quais notas já foram adicionadas na lista, os destaques podem ser desativados temporariamente pelo botão do painel. Caso a camada "Notas" seja excluída ou clicado em X no diálogo, as seleções serão perdidas.

Como funciona?

  • Executar o script
  • Ligar pintura
  • Clique para destacar
  • Clique para remover destaque

Demonstração

Imagem.gif, clique para visualizar.

Código

Última atualização: 2026-01-31

from org.openstreetmap.josm.gui import MainApplication, Notification
from org.openstreetmap.josm.gui.layer import MapViewPaintable, NoteLayer, LayerManager
from javax.swing import (JDialog, JToggleButton, JPanel, JTextArea, JScrollPane, 
    JSlider, JCheckBox, JLabel, SwingUtilities, JOptionPane)
from java.awt import Color, BasicStroke, AlphaComposite, BorderLayout, GridLayout
from java.awt.geom import Path2D
import java.awt.event

# --- Variáveis Globais ---
current_note_painter = None
notes_to_highlight = set()

class NoteHighlighter(MapViewPaintable):
    def __init__(self, ids_set, transparency, fill_enabled):
        self.ids_set = ids_set
        self.transparency = transparency
        self.fill_enabled = fill_enabled

    def paint(self, g, mv, bbox):
        if not self.ids_set: return
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, self.transparency))
        g.setStroke(BasicStroke(1.5))
        for layer in MainApplication.getLayerManager().getLayers():
            if isinstance(layer, NoteLayer):
                all_notes = layer.getData().getNotes()
                for nota in all_notes:
                    if nota.id in self.ids_set:
                        p = mv.getPoint(nota.getLatLon())
                        self._draw_drop(g, p.x, p.y)

    def _draw_drop(self, g, x, y):
        drop = Path2D.Float()
        drop.moveTo(x, y) 
        drop.curveTo(x - 5, y - 5, x - 7, y - 15, x, y - 15)
        drop.curveTo(x + 7, y - 15, x + 5, y - 5, x, y)
        drop.closePath()
        if self.fill_enabled:
            g.setColor(Color.ORANGE)
            g.fill(drop)
        g.setColor(Color.ORANGE)
        g.draw(drop)

# --- Funções de Controle ---
def atualizar_lista_debug():
    """Limpa a depuração e lista apenas os IDs ativos"""
    debug_area.setText("")
    sorted_ids = sorted(list(notes_to_highlight))
    for note_id in sorted_ids:
        debug_area.append("Nota: " + str(note_id) + "\n")

def limpar_pintura_mapa():
    global current_note_painter
    if MainApplication.getMap() and MainApplication.getMap().mapView:
        mv = MainApplication.getMap().mapView
        if current_note_painter:
            mv.removeTemporaryLayer(current_note_painter)
            current_note_painter = None
        mv.removeMouseListener(mouse_listener)
        mv.repaint()

def fechar_dialogo_completo():
    limpar_pintura_mapa()
    MainApplication.getLayerManager().removeLayerChangeListener(layer_listener)
    if dialog.isVisible():
        dialog.dispose()

def handle_click(e):
    if not toggle_btn.isSelected(): return
    if not MainApplication.getMap(): return
    mv = MainApplication.getMap().mapView
    click_p = e.getPoint()
    nota_encontrada = None
    for layer in MainApplication.getLayerManager().getLayers():
        if isinstance(layer, NoteLayer):
            for n in layer.getData().getNotes():
                note_p = mv.getPoint(n.getLatLon())
                if click_p.distance(note_p) < 10:
                    nota_encontrada = n
                    break
    if nota_encontrada:
        if nota_encontrada.id in notes_to_highlight:
            notes_to_highlight.remove(nota_encontrada.id)
        else:
            notes_to_highlight.add(nota_encontrada.id)
        
        atualizar_lista_debug()
        mv.repaint()

def atualizar_desenho(e=None):
    global current_note_painter
    if not MainApplication.getMap(): return
    mv = MainApplication.getMap().mapView
    if toggle_btn.isSelected():
        if current_note_painter:
            mv.removeTemporaryLayer(current_note_painter)
        transp = slider_transp.getValue() / 100.0
        current_note_painter = NoteHighlighter(notes_to_highlight, transp, chk_fill.isSelected())
        mv.addTemporaryLayer(current_note_painter)
        mv.repaint()

def on_toggle(e):
    if not MainApplication.getMap() or not MainApplication.getMap().mapView:
        toggle_btn.setSelected(False)
        return
    if toggle_btn.isSelected():
        MainApplication.getMap().mapView.addMouseListener(mouse_listener)
        atualizar_desenho()
        toggle_btn.setText("PINTURA: ATIVA")
        toggle_btn.setBackground(Color(144, 255, 144))
    else:
        limpar_pintura_mapa()
        toggle_btn.setText("LIGAR PINTURA")
        toggle_btn.setBackground(None)

# --- Monitor de Camadas ---
class MyLayerChangeListener(LayerManager.LayerChangeListener):
    def layerAdded(self, e): pass
    def layerOrderChanged(self, e): pass
    def layerRemoving(self, e):
        if isinstance(e.getRemovedLayer(), NoteLayer):
            def acao_remocao():
                fechar_dialogo_completo()
                Notification(u"Camada de 'Notas' deletada. Fechando diálogo").setIcon(JOptionPane.WARNING_MESSAGE).show()
            SwingUtilities.invokeLater(acao_remocao)

# --- Adaptadores ---
class MapClickAdapter(java.awt.event.MouseAdapter):
    def mousePressed(self, e): handle_click(e)

class WindowCloseAdapter(java.awt.event.WindowAdapter):
    def windowClosing(self, e): fechar_dialogo_completo()

# --- Verificação Inicial ---
def iniciar_script():
    tem_nota = any(isinstance(l, NoteLayer) for l in MainApplication.getLayerManager().getLayers())
    if not tem_nota:
        Notification("Nenhuma camada 'Notas' encontrada.").setIcon(JOptionPane.ERROR_MESSAGE).show()
        return

    global dialog, toggle_btn, chk_fill, slider_transp, debug_area, mouse_listener, layer_listener

    dialog = JDialog(MainApplication.getMainFrame(), "Note Painter", False)
    dialog.setLayout(BorderLayout())

    panel_ctrl = JPanel(GridLayout(0, 1))
    toggle_btn = JToggleButton("LIGAR PINTURA")
    toggle_btn.setOpaque(True)
    toggle_btn.addActionListener(on_toggle)
    chk_fill = JCheckBox("Preenchimento", True)
    chk_fill.addActionListener(atualizar_desenho)
    slider_transp = JSlider(0, 100, 75)
    slider_transp.addChangeListener(atualizar_desenho)

    panel_ctrl.add(toggle_btn)
    panel_ctrl.add(chk_fill)
    panel_ctrl.add(JLabel(u"Transparência:"))
    panel_ctrl.add(slider_transp)

    debug_area = JTextArea(6, 10)
    debug_area.setEditable(False)
    dialog.add(panel_ctrl, BorderLayout.NORTH)
    dialog.add(JScrollPane(debug_area), BorderLayout.CENTER)

    mouse_listener = MapClickAdapter()
    layer_listener = MyLayerChangeListener()
    dialog.addWindowListener(WindowCloseAdapter())
    MainApplication.getLayerManager().addLayerChangeListener(layer_listener)

    dialog.pack()
    dialog.setLocationRelativeTo(MainApplication.getMainFrame())
    dialog.setVisible(True)

iniciar_script()