/**
  * Retries to recover the upload operation from an exception which was thrown because an uploaded
  * primitive was already deleted on the server.
  *
  * @param e the exception throw by the API
  * @param monitor a progress monitor
  * @throws OsmTransferException thrown if we can't recover from the exception
  */
 protected void recoverFromGoneOnServer(OsmApiPrimitiveGoneException e, ProgressMonitor monitor)
     throws OsmTransferException {
   if (!e.isKnownPrimitive()) throw e;
   OsmPrimitive p = layer.data.getPrimitiveById(e.getPrimitiveId(), e.getPrimitiveType());
   if (p == null) throw e;
   if (p.isDeleted()) {
     // we tried to delete an already deleted primitive.
     //
     System.out.println(
         tr(
             "Warning: object ''{0}'' is already deleted on the server. Skipping this object and retrying to upload.",
             p.getDisplayName(DefaultNameFormatter.getInstance())));
     monitor.appendLogMessage(
         tr(
             "Object ''{0}'' is already deleted. Skipping object in upload.",
             p.getDisplayName(DefaultNameFormatter.getInstance())));
     processedPrimitives.addAll(writer.getProcessedPrimitives());
     processedPrimitives.add(p);
     toUpload.removeProcessed(processedPrimitives);
     return;
   }
   // exception was thrown because we tried to *update* an already deleted
   // primitive. We can't resolve this automatically. Re-throw exception,
   // a conflict is going to be created later.
   throw e;
 }
Exemple #2
0
 private void checkNodes() {
   DataSet dataSet = getDataSet();
   if (dataSet != null) {
     Node[] nodes = this.nodes;
     for (Node n : nodes) {
       if (n.getDataSet() != dataSet)
         throw new DataIntegrityProblemException(
             "Nodes in way must be in the same dataset",
             tr("Nodes in way must be in the same dataset"));
       if (n.isDeleted())
         throw new DataIntegrityProblemException(
             "Deleted node referenced: " + toString(),
             "<html>"
                 + tr(
                     "Deleted node referenced by {0}",
                     DefaultNameFormatter.getInstance().formatAsHtmlUnorderedList(this))
                 + "</html>");
     }
     if (Main.pref.getBoolean("debug.checkNullCoor", true)) {
       for (Node n : nodes) {
         if (n.isVisible() && !n.isIncomplete() && !n.isLatLonKnown())
           throw new DataIntegrityProblemException(
               "Complete visible node with null coordinates: " + toString(),
               "<html>"
                   + tr(
                       "Complete node {0} with null coordinates in way {1}",
                       DefaultNameFormatter.getInstance().formatAsHtmlUnorderedList(n),
                       DefaultNameFormatter.getInstance().formatAsHtmlUnorderedList(this))
                   + "</html>");
       }
     }
   }
 }
 /**
  * Internal method that stuffs information into the rendering component provided that it's a kind
  * of JLabel.
  *
  * @param def the rendering component
  * @param value the HistoryOsmPrimtive to render
  * @return the modified rendering component
  */
 private Component renderer(Component def, HistoryOsmPrimitive value) {
   if (value != null && def instanceof JLabel) {
     ((JLabel) def).setText(value.getDisplayName(DefaultNameFormatter.getInstance()));
     ((JLabel) def).setIcon(ImageProvider.get(value.getType()));
     ((JLabel) def).setToolTipText(formatter.buildDefaultToolTip(value));
   }
   return def;
 }
  /**
   * Inform a non-expert user about what relation membership conflict resolution means.
   *
   * @param primitives The primitives to be combined
   * @param parentRelations The parent relations of the primitives
   * @throws UserCancelException If the user cancels the dialog.
   */
  protected static void informAboutRelationMembershipConflicts(
      final Collection<? extends OsmPrimitive> primitives, final Set<Relation> parentRelations)
      throws UserCancelException {
    /* I18n: object count < 2 is not possible */
    String msg =
        trn(
            "You are about to combine {1} object, "
                + "which is part of {0} relation:<br/>{2}"
                + "Combining these objects may break this relation. If you are unsure, please cancel this operation.<br/>"
                + "If you want to continue, you are shown a dialog to decide how to adapt the relation.<br/><br/>"
                + "Do you want to continue?",
            "You are about to combine {1} objects, "
                + "which are part of {0} relations:<br/>{2}"
                + "Combining these objects may break these relations. If you are unsure, please cancel this operation.<br/>"
                + "If you want to continue, you are shown a dialog to decide how to adapt the relations.<br/><br/>"
                + "Do you want to continue?",
            parentRelations.size(),
            parentRelations.size(),
            primitives.size(),
            DefaultNameFormatter.getInstance().formatAsHtmlUnorderedList(parentRelations, 20));

    if (!ConditionalOptionPaneUtil.showConfirmationDialog(
        "combine_tags",
        Main.parent,
        "<html>" + msg + "</html>",
        tr("Combine confirmation"),
        JOptionPane.YES_NO_OPTION,
        JOptionPane.QUESTION_MESSAGE,
        JOptionPane.YES_OPTION)) {
      throw new UserCancelException();
    }
  }
 /**
  * Retries to recover the upload operation from an exception which was thrown because an uploaded
  * primitive was already deleted on the server.
  *
  * @param e the exception throw by the API
  * @param monitor a progress monitor
  * @throws OsmTransferException if we can't recover from the exception
  */
 protected void recoverFromGoneOnServer(OsmApiPrimitiveGoneException e, ProgressMonitor monitor)
     throws OsmTransferException {
   if (!e.isKnownPrimitive()) throw e;
   OsmPrimitive p = layer.data.getPrimitiveById(e.getPrimitiveId(), e.getPrimitiveType());
   if (p == null) throw e;
   if (p.isDeleted()) {
     // we tried to delete an already deleted primitive.
     final String msg;
     final String displayName = p.getDisplayName(DefaultNameFormatter.getInstance());
     if (p instanceof Node) {
       msg = tr("Node ''{0}'' is already deleted. Skipping object in upload.", displayName);
     } else if (p instanceof Way) {
       msg = tr("Way ''{0}'' is already deleted. Skipping object in upload.", displayName);
     } else if (p instanceof Relation) {
       msg = tr("Relation ''{0}'' is already deleted. Skipping object in upload.", displayName);
     } else {
       msg = tr("Object ''{0}'' is already deleted. Skipping object in upload.", displayName);
     }
     monitor.appendLogMessage(msg);
     Main.warn(msg);
     processedPrimitives.addAll(writer.getProcessedPrimitives());
     processedPrimitives.add(p);
     toUpload.removeProcessed(processedPrimitives);
     return;
   }
   // exception was thrown because we tried to *update* an already deleted
   // primitive. We can't resolve this automatically. Re-throw exception,
   // a conflict is going to be created later.
   throw e;
 }
Exemple #6
0
 private static boolean confirmRelationDeletion(Collection<Relation> relations) {
   JPanel msg = new JPanel(new GridBagLayout());
   msg.add(
       new JMultilineLabel(
           "<html>"
               + trn(
                   "You are about to delete {0} relation: {1}"
                       + "<br/>"
                       + "This step is rarely necessary and cannot be undone easily after being uploaded to the server."
                       + "<br/>"
                       + "Do you really want to delete?",
                   "You are about to delete {0} relations: {1}"
                       + "<br/>"
                       + "This step is rarely necessary and cannot be undone easily after being uploaded to the server."
                       + "<br/>"
                       + "Do you really want to delete?",
                   relations.size(),
                   relations.size(),
                   DefaultNameFormatter.getInstance().formatAsHtmlUnorderedList(relations, 20))
               + "</html>"));
   return ConditionalOptionPaneUtil.showConfirmationDialog(
       "delete_relations",
       Main.parent,
       msg,
       tr("Delete relation?"),
       JOptionPane.YES_NO_OPTION,
       JOptionPane.QUESTION_MESSAGE,
       JOptionPane.YES_OPTION);
 }
 protected void updateTitle() {
   if (targetPrimitive == null) {
     setTitle(tr("Conflicts when combining primitives"));
     return;
   }
   if (targetPrimitive instanceof Way) {
     setTitle(
         tr(
             "Conflicts when combining ways - combined way is ''{0}''",
             targetPrimitive.getDisplayName(DefaultNameFormatter.getInstance())));
     helpAction.setHelpTopic(ht("/Action/CombineWay#ResolvingConflicts"));
     getRootPane().putClientProperty("help", ht("/Action/CombineWay#ResolvingConflicts"));
   } else if (targetPrimitive instanceof Node) {
     setTitle(
         tr(
             "Conflicts when merging nodes - target node is ''{0}''",
             targetPrimitive.getDisplayName(DefaultNameFormatter.getInstance())));
     helpAction.setHelpTopic(ht("/Action/MergeNodes#ResolvingConflicts"));
     getRootPane().putClientProperty("help", ht("/Action/MergeNodes#ResolvingConflicts"));
   }
 }
  @Override
  public Object getCorrectionValueAt(int rowIndex, int colIndex) {
    RoleCorrection roleCorrection = getCorrections().get(rowIndex);

    switch (colIndex) {
      case 0:
        return roleCorrection.relation.getDisplayName(DefaultNameFormatter.getInstance());
      case 1:
        return roleCorrection.member.getRole();
      case 2:
        return roleCorrection.newRole;
    }
    return null;
  }
 @Override
 protected void realRun() throws SAXException, IOException, OsmTransferException {
   try {
     Stack<OsmPrimitive> toCheck = new Stack<OsmPrimitive>();
     toCheck.addAll(getPrimitivesToCheckForParents());
     Set<OsmPrimitive> checked = new HashSet<OsmPrimitive>();
     while (!toCheck.isEmpty()) {
       if (canceled) return;
       OsmPrimitive current = toCheck.pop();
       synchronized (this) {
         reader = new OsmServerBackreferenceReader(current);
       }
       getProgressMonitor()
           .subTask(
               tr(
                   "Reading parents of ''{0}''",
                   current.getDisplayName(DefaultNameFormatter.getInstance())));
       DataSet ds = reader.parseOsm(getProgressMonitor().createSubTaskMonitor(1, false));
       synchronized (this) {
         reader = null;
       }
       checked.add(current);
       getProgressMonitor().subTask(tr("Checking for deleted parents in the local dataset"));
       for (OsmPrimitive p : ds.allPrimitives()) {
         if (canceled) return;
         OsmPrimitive myDeletedParent = layer.data.getPrimitiveById(p);
         // our local dataset includes a deleted parent of a primitive we want
         // to delete. Include this parent in the collection of uploaded primitives
         //
         if (myDeletedParent != null && myDeletedParent.isDeleted()) {
           if (!toUpload.contains(myDeletedParent)) {
             toUpload.add(myDeletedParent);
           }
           if (!checked.contains(myDeletedParent)) {
             toCheck.push(myDeletedParent);
           }
         }
       }
     }
   } catch (Exception e) {
     if (canceled)
       // ignore exception
       return;
     lastException = e;
   }
 }
Exemple #10
0
 @Override
 public String getDescriptionText() {
   String msg;
   switch (OsmPrimitiveType.from(osm)) {
     case NODE:
       msg = marktr("Add node {0}");
       break;
     case WAY:
       msg = marktr("Add way {0}");
       break;
     case RELATION:
       msg = marktr("Add relation {0}");
       break;
     default: /* should not happen */
       msg = "";
       break;
   }
   return tr(msg, osm.getDisplayName(DefaultNameFormatter.getInstance()));
 }
Exemple #11
0
  @Override
  public String getDescriptionText() {
    if (toDelete.size() == 1) {
      OsmPrimitive primitive = toDelete.iterator().next();
      String msg = "";
      switch (OsmPrimitiveType.from(primitive)) {
        case NODE:
          msg = marktr("Delete node {0}");
          break;
        case WAY:
          msg = marktr("Delete way {0}");
          break;
        case RELATION:
          msg = marktr("Delete relation {0}");
          break;
      }

      return tr(msg, primitive.getDisplayName(DefaultNameFormatter.getInstance()));
    } else {
      Set<OsmPrimitiveType> typesToDelete = getTypesToDelete();
      String msg = "";
      if (typesToDelete.size() > 1) {
        msg = trn("Delete {0} object", "Delete {0} objects", toDelete.size(), toDelete.size());
      } else {
        OsmPrimitiveType t = typesToDelete.iterator().next();
        switch (t) {
          case NODE:
            msg = trn("Delete {0} node", "Delete {0} nodes", toDelete.size(), toDelete.size());
            break;
          case WAY:
            msg = trn("Delete {0} way", "Delete {0} ways", toDelete.size(), toDelete.size());
            break;
          case RELATION:
            msg =
                trn(
                    "Delete {0} relation",
                    "Delete {0} relations", toDelete.size(), toDelete.size());
            break;
        }
      }
      return msg;
    }
  }
Exemple #12
0
  protected Collection<Command> applyCorrections(
      Map<OsmPrimitive, List<TagCorrection>> tagCorrectionsMap,
      Map<OsmPrimitive, List<RoleCorrection>> roleCorrectionMap,
      String description)
      throws UserCancelException {

    if (!tagCorrectionsMap.isEmpty() || !roleCorrectionMap.isEmpty()) {
      Collection<Command> commands = new ArrayList<Command>();
      Map<OsmPrimitive, TagCorrectionTable> tagTableMap =
          new HashMap<OsmPrimitive, TagCorrectionTable>();
      Map<OsmPrimitive, RoleCorrectionTable> roleTableMap =
          new HashMap<OsmPrimitive, RoleCorrectionTable>();

      final JPanel p = new JPanel(new GridBagLayout());

      final JMultilineLabel label1 = new JMultilineLabel(description);
      label1.setMaxWidth(600);
      p.add(label1, GBC.eop().anchor(GBC.CENTER));

      final JMultilineLabel label2 =
          new JMultilineLabel(tr("Please select which changes you want to apply."));
      label2.setMaxWidth(600);
      p.add(label2, GBC.eop().anchor(GBC.CENTER));

      for (Entry<OsmPrimitive, List<TagCorrection>> entry : tagCorrectionsMap.entrySet()) {
        final OsmPrimitive primitive = entry.getKey();
        final List<TagCorrection> tagCorrections = entry.getValue();

        if (tagCorrections.isEmpty()) {
          continue;
        }

        final JLabel propertiesLabel = new JLabel(tr("Tags of "));
        p.add(propertiesLabel, GBC.std());

        final JLabel primitiveLabel =
            new JLabel(
                primitive.getDisplayName(DefaultNameFormatter.getInstance()) + ":",
                ImageProvider.get(primitive.getDisplayType()),
                JLabel.LEFT);
        p.add(primitiveLabel, GBC.eol());

        final TagCorrectionTable table = new TagCorrectionTable(tagCorrections);
        final JScrollPane scrollPane = new JScrollPane(table);
        p.add(scrollPane, GBC.eop().fill(GBC.HORIZONTAL));

        tagTableMap.put(primitive, table);
      }

      for (Entry<OsmPrimitive, List<RoleCorrection>> entry : roleCorrectionMap.entrySet()) {
        final OsmPrimitive primitive = entry.getKey();
        final List<RoleCorrection> roleCorrections = entry.getValue();

        if (roleCorrections.isEmpty()) {
          continue;
        }

        final JLabel rolesLabel = new JLabel(tr("Roles in relations referring to"));
        p.add(rolesLabel, GBC.std());

        final JLabel primitiveLabel =
            new JLabel(
                primitive.getDisplayName(DefaultNameFormatter.getInstance()),
                ImageProvider.get(primitive.getDisplayType()),
                JLabel.LEFT);
        p.add(primitiveLabel, GBC.eol());

        final RoleCorrectionTable table = new RoleCorrectionTable(roleCorrections);
        final JScrollPane scrollPane = new JScrollPane(table);
        p.add(scrollPane, GBC.eop().fill(GBC.HORIZONTAL));

        roleTableMap.put(primitive, table);
      }

      int answer =
          JOptionPane.showOptionDialog(
              Main.parent,
              p,
              tr("Automatic tag correction"),
              JOptionPane.YES_NO_CANCEL_OPTION,
              JOptionPane.PLAIN_MESSAGE,
              null,
              applicationOptions,
              applicationOptions[0]);

      if (answer == JOptionPane.YES_OPTION) {
        for (Entry<OsmPrimitive, List<TagCorrection>> entry : tagCorrectionsMap.entrySet()) {
          List<TagCorrection> tagCorrections = entry.getValue();
          OsmPrimitive primitive = entry.getKey();

          // create the clone
          OsmPrimitive clone = null;
          if (primitive instanceof Way) {
            clone = new Way((Way) primitive);
          } else if (primitive instanceof Node) {
            clone = new Node((Node) primitive);
          } else if (primitive instanceof Relation) {
            clone = new Relation((Relation) primitive);
          } else throw new AssertionError();

          // use this structure to remember keys that have been set already so that
          // they're not dropped by a later step
          Set<String> keysChanged = new HashSet<String>();

          // apply all changes to this clone
          for (int i = 0; i < tagCorrections.size(); i++) {
            if (tagTableMap.get(primitive).getCorrectionTableModel().getApply(i)) {
              TagCorrection tagCorrection = tagCorrections.get(i);
              if (tagCorrection.isKeyChanged() && !keysChanged.contains(tagCorrection.oldKey)) {
                clone.remove(tagCorrection.oldKey);
              }
              clone.put(tagCorrection.newKey, tagCorrection.newValue);
              keysChanged.add(tagCorrection.newKey);
            }
          }

          // save the clone
          if (!keysChanged.isEmpty()) {
            commands.add(new ChangeCommand(primitive, clone));
          }
        }
        for (Entry<OsmPrimitive, List<RoleCorrection>> entry : roleCorrectionMap.entrySet()) {
          OsmPrimitive primitive = entry.getKey();
          List<RoleCorrection> roleCorrections = entry.getValue();

          for (int i = 0; i < roleCorrections.size(); i++) {
            RoleCorrection roleCorrection = roleCorrections.get(i);
            if (roleTableMap.get(primitive).getCorrectionTableModel().getApply(i)) {
              commands.add(
                  new ChangeRelationMemberRoleCommand(
                      roleCorrection.relation, roleCorrection.position, roleCorrection.newRole));
            }
          }
        }
      } else if (answer != JOptionPane.NO_OPTION) throw new UserCancelException();
      return commands;
    }

    return Collections.emptyList();
  }
 /** Can be overridden to customize the Text */
 protected String getComponentText(OsmPrimitive value) {
   return value.getDisplayName(DefaultNameFormatter.getInstance());
 }
 protected void renderPrimitive(RelationMember member) {
   String displayName = member.getMember().getDisplayName(DefaultNameFormatter.getInstance());
   setText(displayName);
   setToolTipText(DefaultNameFormatter.getInstance().buildDefaultToolTip(member.getMember()));
   setIcon(ImageProvider.get(member.getDisplayType()));
 }
Exemple #15
0
  static SplitWayResult doSplitWay(
      OsmDataLayer layer,
      Way way,
      Way wayToKeep,
      List<Way> newWays,
      List<OsmPrimitive> newSelection) {

    Collection<Command> commandList = new ArrayList<>(newWays.size());
    Collection<String> nowarnroles =
        Main.pref.getCollection(
            "way.split.roles.nowarn",
            Arrays.asList(
                "outer", "inner", "forward", "backward", "north", "south", "east", "west"));

    // Change the original way
    final Way changedWay = new Way(way);
    changedWay.setNodes(wayToKeep.getNodes());
    commandList.add(new ChangeCommand(way, changedWay));
    if (!newSelection.contains(way)) {
      newSelection.add(way);
    }
    newWays.remove(wayToKeep);

    for (Way wayToAdd : newWays) {
      commandList.add(new AddCommand(layer, wayToAdd));
      newSelection.add(wayToAdd);
    }

    boolean warnmerole = false;
    boolean warnme = false;
    // now copy all relations to new way also

    for (Relation r : OsmPrimitive.getFilteredList(way.getReferrers(), Relation.class)) {
      if (!r.isUsable()) {
        continue;
      }
      Relation c = null;
      String type = r.get("type");
      if (type == null) {
        type = "";
      }

      int i_c = 0, i_r = 0;
      List<RelationMember> relationMembers = r.getMembers();
      for (RelationMember rm : relationMembers) {
        if (rm.isWay() && rm.getMember() == way) {
          boolean insert = true;
          if ("restriction".equals(type)) {
            /* this code assumes the restriction is correct. No real error checking done */
            String role = rm.getRole();
            if ("from".equals(role) || "to".equals(role)) {
              OsmPrimitive via = null;
              for (RelationMember rmv : r.getMembers()) {
                if ("via".equals(rmv.getRole())) {
                  via = rmv.getMember();
                }
              }
              List<Node> nodes = new ArrayList<>();
              if (via != null) {
                if (via instanceof Node) {
                  nodes.add((Node) via);
                } else if (via instanceof Way) {
                  nodes.add(((Way) via).lastNode());
                  nodes.add(((Way) via).firstNode());
                }
              }
              Way res = null;
              for (Node n : nodes) {
                if (changedWay.isFirstLastNode(n)) {
                  res = way;
                }
              }
              if (res == null) {
                for (Way wayToAdd : newWays) {
                  for (Node n : nodes) {
                    if (wayToAdd.isFirstLastNode(n)) {
                      res = wayToAdd;
                    }
                  }
                }
                if (res != null) {
                  if (c == null) {
                    c = new Relation(r);
                  }
                  c.addMember(new RelationMember(role, res));
                  c.removeMembersFor(way);
                  insert = false;
                }
              } else {
                insert = false;
              }
            } else if (!"via".equals(role)) {
              warnme = true;
            }
          } else if (!("route".equals(type)) && !("multipolygon".equals(type))) {
            warnme = true;
          }
          if (c == null) {
            c = new Relation(r);
          }

          if (insert) {
            if (rm.hasRole() && !nowarnroles.contains(rm.getRole())) {
              warnmerole = true;
            }

            Boolean backwards = null;
            int k = 1;
            while (i_r - k >= 0 || i_r + k < relationMembers.size()) {
              if ((i_r - k >= 0) && relationMembers.get(i_r - k).isWay()) {
                Way w = relationMembers.get(i_r - k).getWay();
                if ((w.lastNode() == way.firstNode()) || w.firstNode() == way.firstNode()) {
                  backwards = Boolean.FALSE;
                } else if ((w.firstNode() == way.lastNode()) || w.lastNode() == way.lastNode()) {
                  backwards = Boolean.TRUE;
                }
                break;
              }
              if ((i_r + k < relationMembers.size()) && relationMembers.get(i_r + k).isWay()) {
                Way w = relationMembers.get(i_r + k).getWay();
                if ((w.lastNode() == way.firstNode()) || w.firstNode() == way.firstNode()) {
                  backwards = Boolean.TRUE;
                } else if ((w.firstNode() == way.lastNode()) || w.lastNode() == way.lastNode()) {
                  backwards = Boolean.FALSE;
                }
                break;
              }
              k++;
            }

            int j = i_c;
            for (Way wayToAdd : newWays) {
              RelationMember em = new RelationMember(rm.getRole(), wayToAdd);
              j++;
              if ((backwards != null) && backwards) {
                c.addMember(i_c, em);
              } else {
                c.addMember(j, em);
              }
            }
            i_c = j;
          }
        }
        i_c++;
        i_r++;
      }

      if (c != null) {
        commandList.add(new ChangeCommand(layer, r, c));
      }
    }
    if (warnmerole) {
      new Notification(
              tr(
                  "A role based relation membership was copied to all new ways.<br>You should verify this and correct it when necessary."))
          .setIcon(JOptionPane.WARNING_MESSAGE)
          .show();
    } else if (warnme) {
      new Notification(
              tr(
                  "A relation membership was copied to all new ways.<br>You should verify this and correct it when necessary."))
          .setIcon(JOptionPane.WARNING_MESSAGE)
          .show();
    }

    return new SplitWayResult(
        new SequenceCommand(
            /* for correct i18n of plural forms - see #9110 */
            trn(
                "Split way {0} into {1} part",
                "Split way {0} into {1} parts",
                newWays.size(),
                way.getDisplayName(DefaultNameFormatter.getInstance()),
                newWays.size()),
            commandList),
        newSelection,
        way,
        newWays);
  }
 public RecentRelationsMenuItem(Relation relation) {
   super(relation.getDisplayName(DefaultNameFormatter.getInstance()));
   this.relation = relation;
   addActionListener(this);
 }
/**
 * Renderer that renders the objects from an OsmPrimitive as data.
 *
 * <p>Can be used in lists and tables.
 *
 * @author imi
 * @author Frederik Ramm <*****@*****.**>
 */
public class OsmPrimitivRenderer implements ListCellRenderer, TableCellRenderer {
  private DefaultNameFormatter formatter = DefaultNameFormatter.getInstance();

  /** Default list cell renderer - delegate for ListCellRenderer operation */
  private DefaultListCellRenderer defaultListCellRenderer = new DefaultListCellRenderer();

  /** Default table cell renderer - delegate for TableCellRenderer operation */
  private DefaultTableCellRenderer defaultTableCellRenderer = new DefaultTableCellRenderer();

  /** Adapter method supporting the ListCellRenderer interface. */
  @Override
  public Component getListCellRendererComponent(
      JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
    Component def =
        defaultListCellRenderer.getListCellRendererComponent(
            list, value, index, isSelected, cellHasFocus);
    return renderer(def, (OsmPrimitive) value);
  }

  /** Adapter method supporting the TableCellRenderer interface. */
  @Override
  public Component getTableCellRendererComponent(
      JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
    Component def =
        defaultTableCellRenderer.getTableCellRendererComponent(
            table, value, isSelected, hasFocus, row, column);
    if (value instanceof OsmPrimitive) return renderer(def, (OsmPrimitive) value);
    else if (value instanceof HistoryOsmPrimitive)
      return renderer(def, (HistoryOsmPrimitive) value);
    else return def;
  }

  /**
   * Internal method that stuffs information into the rendering component provided that it's a kind
   * of JLabel.
   *
   * @param def the rendering component
   * @param value the OsmPrimtive to render
   * @return the modified rendering component
   */
  private Component renderer(Component def, OsmPrimitive value) {
    if (value != null && def instanceof JLabel) {
      ((JLabel) def).setText(getComponentText(value));
      ImageIcon icon = ImageProvider.get(value.getDisplayType());
      if (icon != null) {
        ((JLabel) def).setIcon(icon);
      } else {
        Main.warn("Null icon for " + value.getDisplayType());
      }
      ((JLabel) def).setToolTipText(getComponentToolTipText(value));
    }
    return def;
  }

  /**
   * Internal method that stuffs information into the rendering component provided that it's a kind
   * of JLabel.
   *
   * @param def the rendering component
   * @param value the HistoryOsmPrimtive to render
   * @return the modified rendering component
   */
  private Component renderer(Component def, HistoryOsmPrimitive value) {
    if (value != null && def instanceof JLabel) {
      ((JLabel) def).setText(value.getDisplayName(DefaultNameFormatter.getInstance()));
      ((JLabel) def).setIcon(ImageProvider.get(value.getType()));
      ((JLabel) def).setToolTipText(formatter.buildDefaultToolTip(value));
    }
    return def;
  }

  /** Can be overridden to customize the Text */
  protected String getComponentText(OsmPrimitive value) {
    return value.getDisplayName(DefaultNameFormatter.getInstance());
  }

  /** Can be overridden to customize the ToolTipText */
  protected String getComponentToolTipText(OsmPrimitive value) {
    return formatter.buildDefaultToolTip(value);
  }
}
 /** Can be overridden to customize the ToolTipText */
 protected String getComponentToolTipText(OsmPrimitive value) {
   return formatter.buildDefaultToolTip(value);
 }
/**
 * Renderer that renders the objects from an OsmPrimitive as data.
 *
 * <p>Can be used in lists and tables.
 *
 * @author imi
 * @author Frederik Ramm
 */
public class OsmPrimitivRenderer implements ListCellRenderer<OsmPrimitive>, TableCellRenderer {
  private final DefaultNameFormatter formatter = DefaultNameFormatter.getInstance();

  /** Default list cell renderer - delegate for ListCellRenderer operation */
  private final DefaultListCellRenderer defaultListCellRenderer = new DefaultListCellRenderer();

  /** Default table cell renderer - delegate for TableCellRenderer operation */
  private final DefaultTableCellRenderer defaultTableCellRenderer = new DefaultTableCellRenderer();

  /** Adapter method supporting the ListCellRenderer interface. */
  @Override
  public Component getListCellRendererComponent(
      JList<? extends OsmPrimitive> list,
      OsmPrimitive value,
      int index,
      boolean isSelected,
      boolean cellHasFocus) {
    Component def =
        defaultListCellRenderer.getListCellRendererComponent(
            list, null, index, isSelected, cellHasFocus);
    return renderer(def, value, list.getModel().getSize() > 1000);
  }

  /** Adapter method supporting the TableCellRenderer interface. */
  @Override
  public Component getTableCellRendererComponent(
      JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
    Component def =
        defaultTableCellRenderer.getTableCellRendererComponent(
            table, value, isSelected, hasFocus, row, column);
    if (value instanceof OsmPrimitive)
      return renderer(def, (OsmPrimitive) value, table.getModel().getRowCount() > 1000);
    else if (value instanceof HistoryOsmPrimitive)
      return renderer(def, (HistoryOsmPrimitive) value);
    else return def;
  }

  /**
   * Internal method that stuffs information into the rendering component provided that it's a kind
   * of JLabel.
   *
   * @param def the rendering component
   * @param value the OsmPrimitive to render
   * @param fast whether the icons should be loaded fast since many items are being displayed
   * @return the modified rendering component
   */
  private Component renderer(Component def, OsmPrimitive value, boolean fast) {
    if (value != null && def instanceof JLabel) {
      ((JLabel) def).setText(getComponentText(value));
      final ImageIcon icon =
          fast
              ? ImageProvider.get(value.getType())
              : ImageProvider.getPadded(
                  value,
                  // Height of component no yet known, assume the default 16px.
                  ImageProvider.ImageSizes.SMALLICON.getImageDimension());
      if (icon != null) {
        ((JLabel) def).setIcon(icon);
      } else {
        Main.warn("Null icon for " + value.getDisplayType());
      }
      ((JLabel) def).setToolTipText(getComponentToolTipText(value));
    }
    return def;
  }

  /**
   * Internal method that stuffs information into the rendering component provided that it's a kind
   * of JLabel.
   *
   * @param def the rendering component
   * @param value the HistoryOsmPrimitive to render
   * @return the modified rendering component
   */
  private Component renderer(Component def, HistoryOsmPrimitive value) {
    if (value != null && def instanceof JLabel) {
      ((JLabel) def).setText(value.getDisplayName(DefaultNameFormatter.getInstance()));
      ((JLabel) def).setIcon(ImageProvider.get(value.getType()));
      ((JLabel) def).setToolTipText(formatter.buildDefaultToolTip(value));
    }
    return def;
  }

  /**
   * Returns the text representing an OSM primitive in a component. Can be overridden to customize
   * the text
   *
   * @param value OSM primitive
   * @return text representing the OSM primitive
   */
  protected String getComponentText(OsmPrimitive value) {
    return value.getDisplayName(DefaultNameFormatter.getInstance());
  }

  /**
   * Returns the text representing an OSM primitive in a tooltip. Can be overridden to customize the
   * ToolTipText
   *
   * @param value OSM primitive
   * @return text representing the OSM primitive
   */
  protected String getComponentToolTipText(OsmPrimitive value) {
    return formatter.buildDefaultToolTip(value);
  }
}