Source code: com/virtuosotechnologies/asaph/standardgui/ChordGroupView.java
1 /*
2 ================================================================================
3
4 FILE: ChordGroupView.java
5
6 PROJECT:
7
8 Virtuoso Utilities
9
10 CONTENTS:
11
12 View of a group of chords associated with one ChordAnnotation
13
14 PROGRAMMERS:
15
16 Daniel Azuma (DA) <dazuma@kagi.com>
17
18 COPYRIGHT:
19
20 Copyright (C) 2003 Daniel Azuma (dazuma@kagi.com)
21
22 This program is free software; you can redistribute it and/or
23 modify it under the terms of the GNU General Public License as
24 published by the Free Software Foundation; either version 2
25 of the License, or (at your option) any later version.
26
27 This program is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU General Public License for more details.
31
32 You should have received a copy of the GNU General Public
33 License along with this program; if not, write to
34 Free Software Foundation, Inc.
35 59 Temple Place, Suite 330
36 Boston, MA 02111-1307 USA
37
38 ================================================================================
39 */
40
41
42 package com.virtuosotechnologies.asaph.standardgui;
43
44
45 import java.awt.Graphics2D;
46 import java.awt.geom.Rectangle2D;
47 import java.util.List;
48 import java.util.ArrayList;
49 import java.util.Iterator;
50
51 import com.virtuosotechnologies.asaph.model.ChordAnnotation;
52
53
54 /**
55 * View of a group of chords associated with one ChordAnnotation
56 */
57 /*package*/ class ChordGroupView
58 {
59 /*package*/ static final class EditResults
60 {
61 private String[] strings_;
62 private int anchor_;
63 private int selView_;
64 private int selPos_;
65
66 private EditResults(
67 String[] strings,
68 int anchor,
69 int selView,
70 int selPos)
71 {
72 strings_ = strings;
73 anchor_ = anchor;
74 selView_ = selView;
75 selPos_ = selPos;
76 }
77
78 /*package*/ String[] getStringArray()
79 {
80 return strings_;
81 }
82
83 /*package*/ int getAnchorView()
84 {
85 return anchor_;
86 }
87
88 /*package*/ int getSelectionView()
89 {
90 return selView_;
91 }
92
93 /*package*/ int getSelectionPos()
94 {
95 return selPos_;
96 }
97
98 public String toString()
99 {
100 StringBuffer buf = new StringBuffer("\"");
101 for (int i=0; i<strings_.length; ++i)
102 {
103 if (i != 0)
104 {
105 buf.append(' ');
106 }
107 buf.append(strings_[i]);
108 }
109 buf.append("\" anchor=").append(Integer.toString(anchor_));
110 buf.append(" view=").append(Integer.toString(selView_));
111 buf.append(" pos=").append(Integer.toString(selPos_));
112 return new String(buf);
113 }
114 }
115
116
117 private ChordAnnotation model_;
118 private float xpos_;
119 private float width_;
120 private float top_;
121 private float bottom_;
122 private LineChordPlaceholderView placeholderView_;
123 private List chordViews_;
124 private int anchorView_;
125 private float leftLimit_;
126 private float rightLimit_;
127
128
129 /**
130 * Constructor
131 */
132 /*package*/ ChordGroupView(
133 ChordAnnotation model,
134 float xpos,
135 float width,
136 float top,
137 float bottom)
138 {
139 model_ = model;
140 xpos_ = xpos;
141 width_ = width;
142 top_ = top;
143 bottom_ = bottom;
144 placeholderView_ = null;
145 chordViews_ = new ArrayList();
146 anchorView_ = model_.getPrecedingChords().length;
147 leftLimit_ = Float.POSITIVE_INFINITY;
148 rightLimit_ = Float.NEGATIVE_INFINITY;
149 }
150
151
152 /*package*/ void setPlaceholderView(
153 LineChordPlaceholderView placeholderView)
154 {
155 placeholderView_ = placeholderView;
156 }
157
158
159 /*package*/ void addChordFragment(
160 ChordFragmentView view)
161 {
162 chordViews_.add(view);
163 leftLimit_ = Math.min(leftLimit_, view.getXPos());
164 rightLimit_ = Math.max(rightLimit_, view.getXPos()+view.getWidth());
165 }
166
167
168 /**
169 * Get model
170 */
171 /*package*/ ChordAnnotation getModel()
172 {
173 return model_;
174 }
175
176
177 /**
178 * Accessor for x position
179 */
180 /*package*/ float getXPos()
181 {
182 return xpos_;
183 }
184
185
186 /**
187 * Get corresponding placeholder view
188 */
189 /*package*/ LineChordPlaceholderView getPlaceholderView()
190 {
191 return placeholderView_;
192 }
193
194
195 /**
196 * Is an x position within the limits
197 */
198 /*package*/ boolean isInXLimits(
199 float x)
200 {
201 return x >= leftLimit_ && x <= rightLimit_;
202 }
203
204
205 /**
206 * Get left limit
207 */
208 /*package*/ float getLeftLimit()
209 {
210 return leftLimit_;
211 }
212
213
214 /**
215 * Get right limit
216 */
217 /*package*/ float getRightLimit()
218 {
219 return rightLimit_;
220 }
221
222
223 /**
224 * Set left limit
225 */
226 /*package*/ void setLeftLimit(
227 float limit)
228 {
229 leftLimit_ = limit;
230 }
231
232
233 /**
234 * Set right limit
235 */
236 /*package*/ void setRightLimit(
237 float limit)
238 {
239 rightLimit_ = limit;
240 }
241
242
243 /**
244 * Get number of chord fragment views
245 */
246 /*package*/ int getFragmentCount()
247 {
248 return chordViews_.size();
249 }
250
251
252 /**
253 * Get indexed chord fragment view
254 */
255 /*package*/ ChordFragmentView getNthChordFragment(
256 int n)
257 {
258 return (ChordFragmentView)chordViews_.get(n);
259 }
260
261
262 /**
263 * Draw
264 */
265 /*package*/ void paintBackground(
266 Graphics2D g2d,
267 float x,
268 float y)
269 {
270 g2d.setColor(EditorConstants.BACKGROUND_COLOR);
271 g2d.fill(new Rectangle2D.Float(
272 x+xpos_-1, y+top_-1, width_+1, bottom_-top_+1));
273 }
274
275
276 /**
277 * Draw
278 */
279 /*package*/ void paint(
280 Graphics2D g2d,
281 float x,
282 float y)
283 {
284 g2d.setColor(EditorConstants.CHORD_GROUP_BORDER_COLOR);
285 g2d.draw(new Rectangle2D.Float(
286 x+xpos_, y+top_, width_-1, bottom_-top_-1));
287
288 for (Iterator iter = chordViews_.iterator(); iter.hasNext(); )
289 {
290 ChordFragmentView view = (ChordFragmentView)iter.next();
291 view.paint(g2d, x, y);
292 }
293 }
294
295
296 /*package*/ EditResults getReplacementResults(
297 int leftView,
298 int leftPos,
299 int rightView,
300 int rightPos,
301 String replacement)
302 {
303 List stringList = new ArrayList();
304
305 int preLen = fillStringList(0, 0, leftView, leftPos, stringList);
306 int[] breakPos = fillStringList(replacement, stringList);
307 int postLen = fillStringList(rightView, rightPos, chordViews_.size()-1,
308 ((ChordFragmentView)chordViews_.get(chordViews_.size()-1)).getText().length(),
309 stringList);
310
311 int selView = stringList.size()-postLen;
312 int selPos = breakPos[1];
313 int nAnchor;
314 if (rightView < anchorView_/* || (rightView == anchorView_ && rightPos == 0)*/)
315 {
316 nAnchor = anchorView_-chordViews_.size()+stringList.size();
317 }
318 else if (leftView >= anchorView_)
319 {
320 nAnchor = anchorView_;
321 }
322 else
323 {
324 nAnchor = preLen-1;
325 }
326
327 String[] stringArray = new String[stringList.size()];
328 stringList.toArray(stringArray);
329 return new EditResults(stringArray, nAnchor, selView, selPos);
330 }
331
332
333 private int[] fillStringList(
334 String string,
335 java.util.List list)
336 {
337 boolean first = true;
338 int prePos = 0;
339 int postPos = 0;
340 int index = 0;
341 while (index <= string.length())
342 {
343 int index2 = string.indexOf(' ', index);
344 if (index2 == -1)
345 {
346 index2 = string.length();
347 }
348 String str = string.substring(index, index2);
349 index = index2+1;
350 if (first && !list.isEmpty())
351 {
352 String merge = (String)list.get(list.size()-1);
353 prePos = merge.length();
354 str = merge+str;
355 list.set(list.size()-1, str);
356 }
357 else
358 {
359 list.add(str);
360 }
361 first = false;
362 postPos = str.length();
363 }
364 return new int[]{prePos, postPos};
365 }
366
367
368 private int fillStringList(
369 int leftView,
370 int leftPos,
371 int rightView,
372 int rightPos,
373 java.util.List list)
374 {
375 for (int i=leftView; i<=rightView; ++i)
376 {
377 String str = ((ChordFragmentView)chordViews_.get(i)).getText();
378 if (leftView == rightView)
379 {
380 str = str.substring(leftPos, rightPos);
381 }
382 else if (i == leftView)
383 {
384 str = str.substring(leftPos);
385 }
386 else if (i == rightView)
387 {
388 str = str.substring(0, rightPos);
389 }
390 if (i == leftView && !list.isEmpty())
391 {
392 String merge = (String)list.get(list.size()-1);
393 list.set(list.size()-1, merge+str);
394 }
395 else
396 {
397 list.add(str);
398 }
399 }
400 return rightView-leftView+1;
401 }
402
403
404 /*package*/ String getRangeAsString(
405 int leftView,
406 int leftPos,
407 int rightView,
408 int rightPos)
409 {
410 StringBuffer buf = new StringBuffer();
411 for (int i=leftView; i<=rightView; ++i)
412 {
413 if (i > leftView)
414 {
415 buf.append(' ');
416 }
417 String str = ((ChordFragmentView)chordViews_.get(i)).getText();
418 if (i == leftView)
419 {
420 buf.append(str.substring(leftPos));
421 }
422 else if (i == rightView)
423 {
424 buf.append(str.substring(0, rightPos));
425 }
426 else
427 {
428 buf.append(str);
429 }
430 }
431 return new String(buf);
432 }
433 }