001/* 002 * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games. 003 * Copyright (C) 2000-2011 The Gridarta Developers. 004 * 005 * This program is free software; you can redistribute it and/or modify 006 * it under the terms of the GNU General Public License as published by 007 * the Free Software Foundation; either version 2 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU General Public License for more details. 014 * 015 * You should have received a copy of the GNU General Public License along 016 * with this program; if not, write to the Free Software Foundation, Inc., 017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 018 */ 019 020package net.sf.gridarta.gui.dialog.plugin.parameter; 021 022import java.util.ArrayList; 023import java.util.Collection; 024import java.util.Collections; 025import java.util.Comparator; 026import java.util.List; 027import javax.swing.AbstractListModel; 028import javax.swing.ComboBoxModel; 029import net.sf.gridarta.model.archetype.Archetype; 030import net.sf.gridarta.model.archetypeset.ArchetypeSet; 031import net.sf.gridarta.model.gameobject.GameObject; 032import net.sf.gridarta.model.maparchobject.MapArchObject; 033import org.jetbrains.annotations.NotNull; 034import org.jetbrains.annotations.Nullable; 035 036public class ArchComboBoxModel<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> extends AbstractListModel implements ComboBoxModel { 037 038 @Nullable 039 private Object value; 040 041 @NotNull 042 private final List<Archetype<G, A, R>> archList; 043 044 // FIXME: This constant looks pretty pointless. 045 046 @NotNull 047 private static final String CURRENT_FILTER = ""; 048 049 private static final long serialVersionUID = 1L; 050 051 public ArchComboBoxModel(@NotNull final ArchetypeSet<G, A, R> archetypeSet) { 052 final Collection<R> archetypes = archetypeSet.getArchetypes(); 053 archList = new ArrayList<Archetype<G, A, R>>(archetypes); 054 Collections.sort(archList, new Comparator<Archetype<G, A, R>>() { 055 056 @Override 057 public int compare(final Archetype<G, A, R> o1, final Archetype<G, A, R> o2) { 058 return o1.getArchetypeName().toLowerCase().compareTo(o2.getArchetypeName().toLowerCase()); 059 } 060 }); 061 } 062 063 @Nullable 064 @Override 065 public Object getSelectedItem() { 066 return value; 067 } 068 069 @Override 070 public void setSelectedItem(final Object anItem) { 071 value = anItem; 072 } 073 074 @Override 075 public int getSize() { 076 return archList.size(); 077 } 078 079 @NotNull 080 @Override 081 public Object getElementAt(final int index) { 082 return archList.get(index); 083 } 084 085 public void setFilter(@NotNull final String filter) { 086 if (filter.startsWith(CURRENT_FILTER)) { 087 narrowFilter(filter); 088 } else if (CURRENT_FILTER.startsWith(filter)) { 089 enlargeFilter(filter); 090 } else { 091 final int p = getCommonPrefix(CURRENT_FILTER, filter); 092 enlargeFilter(filter.substring(0, p)); 093 narrowFilter(filter); 094 } 095 fireContentsChanged(this, 0, archList.size()); 096 } 097 098 private static int getCommonPrefix(@NotNull final CharSequence s1, @NotNull final CharSequence s2) { 099 int i = 0; 100 while (s1.length() > i && s2.length() > i && s1.charAt(i) == s2.charAt(i)) { 101 i++; 102 } 103 return i; 104 } 105 106 private void enlargeFilter(@NotNull final String filter) { 107 // "abcd" -> "abc" 108 } 109 110 private void narrowFilter(@NotNull final String filter) { 111 // "abc" -> "abcd" 112 } 113 114 /** 115 * @noinspection TypeMayBeWeakened 116 */ 117 @NotNull 118 public Archetype<G, A, R> getNearestMatch(@NotNull final String name) { 119 int pos = Collections.binarySearch(archList, name, new Comparator<Object>() { 120 121 @Override 122 public int compare(final Object o1, final Object o2) { 123 final String s1; 124 if (o1 instanceof Archetype) { 125 s1 = ((Archetype<?, ?, ?>) o1).getArchetypeName(); 126 } else { 127 s1 = o1.toString(); 128 } 129 final String s2; 130 if (o2 instanceof Archetype) { 131 s2 = ((Archetype<?, ?, ?>) o2).getArchetypeName(); 132 } else { 133 s2 = o2.toString(); 134 } 135 return s1.compareToIgnoreCase(s2); 136 } 137 }); 138 if (pos < 0) { 139 pos = -(pos + 1); 140 } 141 if (pos >= archList.size()) { 142 pos = archList.size() - 1; 143 } 144 if (pos < 0) { 145 pos = 0; 146 } 147 return archList.get(pos); 148 } 149 150}