PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/docking-frames-core/src/bibliothek/extension/gui/dock/preference/MergedPreferenceModel.java

https://github.com/paranoia25/DockingFrames
Java | 423 lines | 252 code | 61 blank | 110 comment | 57 complexity | 64cc5a8f64f1bdd9a1621e3db0a358c9 MD5 | raw file
  1. /*
  2. * Bibliothek - DockingFrames
  3. * Library built on Java/Swing, allows the user to "drag and drop"
  4. * panels containing any Swing-Component the developer likes to add.
  5. *
  6. * Copyright (C) 2008 Benjamin Sigg
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. *
  22. * Benjamin Sigg
  23. * benjamin_sigg@gmx.ch
  24. * CH - Switzerland
  25. */
  26. package bibliothek.extension.gui.dock.preference;
  27. import java.util.ArrayList;
  28. import java.util.List;
  29. import bibliothek.gui.DockController;
  30. import bibliothek.util.Path;
  31. import bibliothek.util.PathCombiner;
  32. /**
  33. * A preference model that envelops other models and uses their preferences. This model
  34. * makes use of a {@link PathCombiner} to create unique identifiers for all preferences of its
  35. * sub-models.
  36. * @author Benjamin Sigg
  37. */
  38. public class MergedPreferenceModel extends AbstractPreferenceModel{
  39. private List<Model> models = new ArrayList<Model>();
  40. /** how to create the result of {@link #getPath(int)} */
  41. private PathCombiner combiner = PathCombiner.UNIQUE;
  42. private PreferenceModelListener listener = new PreferenceModelListener(){
  43. public void preferenceAdded( PreferenceModel model, int beginIndex, int endIndex ){
  44. int begin = indexAt( model, beginIndex );
  45. int end = begin + (endIndex - beginIndex);
  46. firePreferenceAdded( begin, end );
  47. }
  48. public void preferenceChanged( PreferenceModel model, int beginIndex, int endIndex ){
  49. int begin = indexAt( model, beginIndex );
  50. int end = begin + (endIndex - beginIndex);
  51. firePreferenceChanged( begin, end );
  52. }
  53. public void preferenceRemoved( PreferenceModel model, int beginIndex, int endIndex ){
  54. int begin = indexAt( model, beginIndex );
  55. int end = begin + (endIndex - beginIndex);
  56. firePreferenceRemoved( begin, end );
  57. }
  58. };
  59. /**
  60. * Creates a new model
  61. * @param controller the controller in whose realm this model is used
  62. */
  63. public MergedPreferenceModel( DockController controller ){
  64. super( controller );
  65. }
  66. /**
  67. * Creates a new path.
  68. * @param combiner tells how to combine the path of a model and of
  69. * its preferences in {@link #getPath(int)}. Not <code>null</code>.
  70. * @param controller the controller in whose realm this model is used
  71. */
  72. public MergedPreferenceModel( PathCombiner combiner, DockController controller ){
  73. super( controller );
  74. if( combiner == null )
  75. throw new IllegalArgumentException( "combiner must not be null" );
  76. this.combiner = combiner;
  77. }
  78. /**
  79. * Adds <code>model</code> at the end of this model.
  80. * @param model the additional model
  81. * @param path the location of the new model
  82. * @see #insert(int, PreferenceModel, Path)
  83. */
  84. public void add( PreferenceModel model, Path path ){
  85. insert( models.size(), model, path );
  86. }
  87. /**
  88. * Inserts a new submodel into this model.
  89. * @param index the location of the new model
  90. * @param model the new model
  91. * @param path the path of the new model, the path must be unique compared
  92. * to the paths of any other model.
  93. */
  94. public void insert( int index, PreferenceModel model, Path path ){
  95. if( this == model )
  96. throw new IllegalArgumentException( "model must not be this" );
  97. for( Model check : models ){
  98. if( check.model == model )
  99. throw new IllegalArgumentException( "can't add a model twice" );
  100. if( check.path.equals( path ))
  101. throw new IllegalArgumentException( "there is already a model with the path " + path );
  102. }
  103. Model insert = new Model();
  104. insert.model = model;
  105. insert.path = path;
  106. models.add( index, insert );
  107. if( hasListeners() )
  108. model.addPreferenceModelListener( listener );
  109. int size = model.getSize();
  110. if( size > 0 ){
  111. int begin = 0;
  112. for( int i = 0; i < index; i++ ){
  113. begin += models.get( i ).model.getSize();
  114. }
  115. firePreferenceAdded( begin, begin+size-1 );
  116. }
  117. }
  118. /**
  119. * Removes the <code>index'th</code> model of this merged model.
  120. * @param index the location of a child
  121. */
  122. public void remove( int index ){
  123. Model model = models.remove( index );
  124. if( hasListeners() )
  125. model.model.removePreferenceModelListener( listener );
  126. int size = model.model.getSize();
  127. if( size > 0 ){
  128. int begin = 0;
  129. for( int i = 0; i < index; i++ ){
  130. begin += models.get( i ).model.getSize();
  131. }
  132. firePreferenceRemoved( begin, begin+size-1 );
  133. }
  134. }
  135. /**
  136. * Removes <code>model</code> from this merged model.
  137. * @param model the model to remove
  138. */
  139. public void remove( MergedPreferenceModel model ){
  140. int index = indexOf( model );
  141. if( index >= 0 )
  142. remove( index );
  143. }
  144. /**
  145. * Removes the model with the path <code>path</code>.
  146. * @param path some path
  147. */
  148. public void remove( Path path ){
  149. int index = indexOf( path );
  150. if( index >= 0 )
  151. remove( index );
  152. }
  153. /**
  154. * Removes all children from this model.
  155. */
  156. public void clear(){
  157. int size = getSize();
  158. if( hasListeners() ){
  159. for( Model model : models ){
  160. model.model.removePreferenceModelListener( listener );
  161. }
  162. }
  163. models.clear();
  164. if( size > 0 ){
  165. firePreferenceRemoved( 0, size-1 );
  166. }
  167. }
  168. /**
  169. * Gets the index of <code>model</code>.
  170. * @param model some model to search
  171. * @return the index or -1 if not found
  172. */
  173. public int indexOf( PreferenceModel model ){
  174. int i = 0;
  175. for( Model check : models ){
  176. if( check.model == model )
  177. return i;
  178. i++;
  179. }
  180. return -1;
  181. }
  182. /**
  183. * Gets the index of <code>path</code>.
  184. * @param path the path of some model
  185. * @return the index or -1 if not found
  186. */
  187. public int indexOf( Path path ){
  188. int i = 0;
  189. for( Model check : models ){
  190. if( check.path.equals( path ) )
  191. return i;
  192. i++;
  193. }
  194. return -1;
  195. }
  196. /**
  197. * Gets the <code>index</code>'th model of this merged model.
  198. * @param index some index
  199. * @return a child of this model
  200. */
  201. public PreferenceModel getModel( int index ){
  202. return models.get( index ).model;
  203. }
  204. /**
  205. * Gets the model which was stored using the key <code>path</code>.
  206. * @param path the path of the model
  207. * @return the model or <code>null</code> if not found
  208. */
  209. public PreferenceModel getModel( Path path ){
  210. int index = indexOf( path );
  211. if( index < 0 ){
  212. return null;
  213. }
  214. return getModel( index );
  215. }
  216. @Override
  217. public void read() {
  218. for( Model model : models ){
  219. model.model.read();
  220. }
  221. }
  222. @Override
  223. public void write() {
  224. for( Model model : models ){
  225. model.model.write();
  226. }
  227. }
  228. @Override
  229. public void addPreferenceModelListener( PreferenceModelListener listener ) {
  230. boolean hadListeners = hasListeners();
  231. super.addPreferenceModelListener( listener );
  232. if( hasListeners() && !hadListeners ){
  233. for( Model model : models ){
  234. model.model.addPreferenceModelListener( this.listener );
  235. }
  236. }
  237. }
  238. @Override
  239. public void removePreferenceModelListener( PreferenceModelListener listener ) {
  240. boolean hadListeners = hasListeners();
  241. super.removePreferenceModelListener( listener );
  242. if( !hasListeners() && hadListeners ){
  243. for( Model model : models ){
  244. model.model.removePreferenceModelListener( this.listener );
  245. }
  246. }
  247. }
  248. public int getSize() {
  249. int size = 0;
  250. for( Model model : models ){
  251. size += model.model.getSize();
  252. }
  253. return size;
  254. }
  255. public String getLabel( int index ) {
  256. Index local = indexAt( index );
  257. if( local == null )
  258. throw new ArrayIndexOutOfBoundsException( index );
  259. return local.model.model.getLabel( local.index );
  260. }
  261. @Override
  262. public String getDescription( int index ) {
  263. Index local = indexAt( index );
  264. if( local == null )
  265. throw new ArrayIndexOutOfBoundsException( index );
  266. return local.model.model.getDescription( local.index );
  267. }
  268. public Object getValueInfo(int index) {
  269. Index local = indexAt( index );
  270. if( local == null )
  271. throw new ArrayIndexOutOfBoundsException( index );
  272. return local.model.model.getValueInfo( local.index );
  273. }
  274. public Object getValue( int index ) {
  275. Index local = indexAt( index );
  276. if( local == null )
  277. throw new ArrayIndexOutOfBoundsException( index );
  278. return local.model.model.getValue( local.index );
  279. }
  280. public void setValue( int index, Object value ) {
  281. Index local = indexAt( index );
  282. if( local == null )
  283. throw new ArrayIndexOutOfBoundsException( index );
  284. local.model.model.setValue( local.index, value );
  285. }
  286. public Path getTypePath( int index ) {
  287. Index local = indexAt( index );
  288. if( local == null )
  289. throw new ArrayIndexOutOfBoundsException( index );
  290. return local.model.model.getTypePath( local.index );
  291. }
  292. public Path getPath( int index ) {
  293. Index local = indexAt( index );
  294. if( local == null )
  295. throw new ArrayIndexOutOfBoundsException( index );
  296. return combiner.combine( local.model.path, local.model.model.getPath( local.index ) );
  297. }
  298. @Override
  299. public boolean isNatural( int index ) {
  300. Index local = indexAt( index );
  301. if( local == null )
  302. throw new ArrayIndexOutOfBoundsException( index );
  303. return local.model.model.isNatural( local.index );
  304. }
  305. @Override
  306. public void setValueNatural( int index ) {
  307. Index local = indexAt( index );
  308. if( local == null )
  309. throw new ArrayIndexOutOfBoundsException( index );
  310. local.model.model.setValueNatural( local.index );
  311. }
  312. /**
  313. * Gets the model and the index that <code>globalIndex</code> describe in
  314. * this model.
  315. * @param globalIndex some global index
  316. * @return the local index
  317. */
  318. protected Index indexAt( int globalIndex ){
  319. for( Model model : models ){
  320. int size = model.model.getSize();
  321. if( globalIndex < size )
  322. return new Index( model, globalIndex );
  323. else
  324. globalIndex -= size;
  325. }
  326. return null;
  327. }
  328. /**
  329. * Finds the global index if <code>index</code> is part of <code>model</code>.
  330. * @param model a child of this model
  331. * @param index an index in <code>model</code>
  332. * @return the global index
  333. */
  334. protected int indexAt( PreferenceModel model, int index ){
  335. for( Model check : models ){
  336. if( check.model == model )
  337. return index;
  338. index += check.model.getSize();
  339. }
  340. return index;
  341. }
  342. /**
  343. * Describes an index in one of the childen of a {@link MergedPreferenceModel}.
  344. * @author Benjamin Sigg
  345. */
  346. protected static class Index{
  347. public Model model;
  348. public int index;
  349. public Index( Model model, int index ){
  350. this.model = model;
  351. this.index = index;
  352. }
  353. }
  354. /**
  355. * A sub-model entry of a {@link MergedPreferenceModel}.
  356. * @author Benjamin Sigg
  357. */
  358. private static class Model{
  359. public PreferenceModel model;
  360. public Path path;
  361. }
  362. }