1 /*
2  * Created on 30-nov-2005
3  *
4  * TODO To change the template for this generated file go to
5  * Window - Preferences - Java - Code Style - Code Templates
6  */
7 package org.herac.tuxguitar.gui.editors.tab;
8 
9 import java.util.Iterator;
10 import java.util.List;
11 
12 import org.herac.tuxguitar.gui.TuxGuitar;
13 import org.herac.tuxguitar.gui.editors.TGPainter;
14 import org.herac.tuxguitar.gui.editors.tab.layout.ViewLayout;
15 import org.herac.tuxguitar.gui.util.MidiTickUtil;
16 import org.herac.tuxguitar.song.managers.TGMeasureManager;
17 import org.herac.tuxguitar.song.managers.TGSongManager;
18 import org.herac.tuxguitar.song.models.TGBeat;
19 import org.herac.tuxguitar.song.models.TGDuration;
20 import org.herac.tuxguitar.song.models.TGNote;
21 import org.herac.tuxguitar.song.models.TGString;
22 import org.herac.tuxguitar.song.models.TGVelocities;
23 import org.herac.tuxguitar.song.models.TGVoice;
24 
25 /**
26  * @author julian
27  *
28  * TODO To change the template for this generated type comment go to Window - Preferences - Java - Code Style - Code Templates
29  */
30 public class Caret {
31 	private Tablature tablature;
32 	private TGTrackImpl selectedTrack;
33 	private TGMeasureImpl selectedMeasure;
34 	private TGBeat selectedBeat;
35 	private TGNote selectedNote;
36 	private TGDuration selectedDuration;
37 	private long position;
38 	private int string;
39 	private int voice;
40 	private int velocity;
41 	private boolean restBeat;
42 	private boolean changes;
43 
Caret(Tablature tablature)44 	public Caret(Tablature tablature) {
45 		this.tablature = tablature;
46 		this.selectedDuration = getSongManager().getFactory().newDuration();
47 		this.string = 1;
48 		this.velocity = TGVelocities.DEFAULT;
49 		this.changes = false;
50 	}
51 
update()52 	public synchronized void update(){
53 		int trackNumber = (this.selectedTrack != null)?this.selectedTrack.getNumber():1;
54 		update(trackNumber,this.position,this.string);
55 	}
56 
update(int trackNumber)57 	public synchronized void update(int trackNumber){
58 		update(trackNumber,this.position,this.string);
59 	}
60 
update(int trackNumber,long position,int string)61 	public synchronized void update(int trackNumber,long position,int string){
62 		update(trackNumber, position, string,getVelocity());
63 	}
64 
update(int trackNumber,long position,int string,int velocity)65 	public synchronized void update(int trackNumber,long position,int string,int velocity) {
66 		long realPosition = ((TuxGuitar.instance().getPlayer().isRunning())?MidiTickUtil.getStart(TuxGuitar.instance().getPlayer().getTickPosition()):position);
67 		TGTrackImpl track = findTrack(trackNumber);
68 		TGMeasureImpl measure = findMeasure(realPosition,track);
69 		TGBeat beat = findBeat(realPosition,measure);
70 		if(track != null && measure != null && beat != null){
71 			moveTo(track, measure, beat,string);
72 		}
73 		setVelocity(velocity);
74 	}
75 
moveTo(TGTrackImpl selectedTrack, TGMeasureImpl selectedMeasure, TGBeat selectedBeat,int string)76 	public void moveTo(TGTrackImpl selectedTrack, TGMeasureImpl selectedMeasure, TGBeat selectedBeat,int string) {
77 		this.selectedTrack = selectedTrack;
78 		this.selectedMeasure = selectedMeasure;
79 		this.selectedBeat = selectedBeat;
80 		this.string = string;
81 		this.updatePosition();
82 		this.updateDuration();
83 		this.updateString();
84 		this.updateNote();
85 		this.updateBeat();
86 		this.checkTransport();
87 		this.setChanges(true);
88 	}
89 
findTrack(int number)90 	private TGTrackImpl findTrack(int number){
91 		TGTrackImpl track = (TGTrackImpl)getSongManager().getTrack(number);
92 		if(track == null){
93 			track = (TGTrackImpl)getSongManager().getFirstTrack();
94 		}
95 		return track;
96 	}
97 
findMeasure(long position,TGTrackImpl track)98 	private TGMeasureImpl findMeasure(long position,TGTrackImpl track){
99 		TGMeasureImpl measure = null;
100 		if(track != null){
101 			measure = (TGMeasureImpl)getSongManager().getTrackManager().getMeasureAt(track,position);
102 			if(measure == null){
103 				measure = (TGMeasureImpl)getSongManager().getTrackManager().getFirstMeasure(track);
104 			}
105 		}
106 		return measure;
107 	}
108 
findBeat(long position,TGMeasureImpl measure)109 	private TGBeat findBeat(long position,TGMeasureImpl measure){
110 		TGBeat beat = null;
111 		if(measure != null){
112 			TGMeasureManager manager = getSongManager().getMeasureManager();
113 			TGVoice voice = manager.getVoiceIn(measure, position, getVoice());
114 			if( voice != null ){
115 				beat = voice.getBeat();
116 			}
117 			if (beat == null) {
118 				beat = manager.getFirstBeat(measure.getBeats());
119 			}
120 		}
121 		return beat;
122 	}
123 
goToTickPosition()124 	public synchronized void goToTickPosition(){
125 		long start = MidiTickUtil.getStart(TuxGuitar.instance().getPlayer().getTickPosition());
126 		this.update(this.selectedTrack.getNumber(),start,this.string);
127 		this.setChanges(true);
128 	}
129 
paintCaret(ViewLayout layout,TGPainter painter)130 	public void paintCaret(ViewLayout layout,TGPainter painter) {
131 		if(!TuxGuitar.instance().getPlayer().isRunning()){
132 			if (this.selectedMeasure != null && this.selectedBeat instanceof TGBeatImpl) {
133 				TGBeatImpl beat = (TGBeatImpl)this.selectedBeat;
134 				if( (layout.getStyle() & ViewLayout.DISPLAY_TABLATURE) != 0){
135 					boolean expectedVoice = (getSelectedNote() == null || getSelectedNote().getVoice().getIndex() == getVoice());
136 					int stringSpacing = this.tablature.getViewLayout().getStringSpacing();
137 					int leftSpacing = beat.getMeasureImpl().getHeaderImpl().getLeftSpacing(layout);
138 					int x = this.selectedMeasure.getPosX() + beat.getPosX() + beat.getSpacing() + leftSpacing - 5;
139 					int y = this.selectedMeasure.getPosY() + this.selectedMeasure.getTs().getPosition(TGTrackSpacing.POSITION_TABLATURE) + ((this.string * stringSpacing) - stringSpacing) - 7;
140 					int width = 14;
141 					int height = 14;
142 					layout.setCaretStyle(painter, expectedVoice);
143 					painter.initPath();
144 					painter.setAntialias(false);
145 					painter.addRectangle(x, y, width, height);
146 					painter.closePath();
147 				}
148 				else if( (layout.getStyle() & ViewLayout.DISPLAY_SCORE) != 0){
149 					int line = this.tablature.getViewLayout().getScoreLineSpacing();
150 					int leftSpacing = beat.getMeasureImpl().getHeaderImpl().getLeftSpacing(layout);
151 					float xMargin = (2.0f * layout.getScale());
152 					float x1 = this.selectedMeasure.getPosX() + beat.getPosX() + beat.getSpacing() + leftSpacing - xMargin;
153 					float x2 = (x1 + layout.getResources().getScoreNoteWidth() + xMargin);
154 					float y1 = this.selectedMeasure.getPosY() + this.selectedMeasure.getTs().getPosition(TGTrackSpacing.POSITION_TOP) - line;
155 					float y2 = this.selectedMeasure.getPosY() + this.selectedMeasure.getTs().getPosition(TGTrackSpacing.POSITION_BOTTOM);
156 					layout.setCaretStyle(painter, true);
157 					painter.initPath();
158 					painter.moveTo(x1, y1);
159 					painter.lineTo(x1 + ((x2 - x1) / 2f), y1 + (line / 2f));
160 					painter.lineTo(x2, y1);
161 					painter.moveTo(x1, y2 + line);
162 					painter.lineTo(x1 + ((x2 - x1) / 2f), y2 + (line / 2f));
163 					painter.lineTo(x2, y2 + line);
164 					painter.closePath();
165 				}
166 			}
167 		}
168 	}
169 
moveRight()170 	public boolean moveRight() {
171 		if (getSelectedBeat() != null) {
172 			TGMeasureImpl measure = getMeasure();
173 			TGVoice voice = getSongManager().getMeasureManager().getNextVoice(measure.getBeats(),getSelectedBeat(), getVoice());
174 			TGBeat beat = (voice != null ? voice.getBeat() : null );
175 			if (beat == null){
176 				//si no habia mas componentes. busco el siguiente compas
177 				measure = (TGMeasureImpl)getSongManager().getTrackManager().getNextMeasure(getMeasure());
178 				if (measure == null) {
179 					return false;
180 				}
181 				voice = getSongManager().getMeasureManager().getFirstVoice(measure.getBeats(), getVoice());
182 				beat = (voice != null ? voice.getBeat() : null );
183 				if( beat == null ){
184 					beat = getSongManager().getMeasureManager().getFirstBeat(measure.getBeats());
185 				}
186 			}
187 			if(beat != null){
188 				moveTo(getTrack(), measure, beat, getStringNumber());
189 			}
190 		}
191 		return true;
192 	}
193 
moveLeft()194 	public void moveLeft() {
195 		if (getSelectedBeat() != null) {
196 			TGMeasureImpl measure = getMeasure();
197 			TGVoice voice = getSongManager().getMeasureManager().getPreviousVoice(measure.getBeats(),getSelectedBeat(), getVoice());
198 			TGBeat beat = (voice != null ? voice.getBeat() : null );
199 			if (beat == null) {
200 				//si no habia mas componentes. busco el compas anterior
201 				measure = (TGMeasureImpl)getSongManager().getTrackManager().getPrevMeasure(getMeasure());
202 				if (measure == null) {
203 					return;
204 				}
205 				voice = getSongManager().getMeasureManager().getLastVoice(measure.getBeats(), getVoice());
206 				beat = (voice != null ? voice.getBeat() : null );
207 				if( beat == null ){
208 					beat = getSongManager().getMeasureManager().getFirstBeat(measure.getBeats());
209 				}
210 			}
211 			if(beat != null){
212 				moveTo(getTrack(), measure, beat, getStringNumber());
213 			}
214 		}
215 	}
216 
217 	/**
218 	 * Luego de mover el Caret. cambia la duracion seleccionada por la del componente. solo si lo que resta del compas no esta vacio
219 	 */
updateDuration()220 	private void updateDuration() {
221 		if (this.selectedBeat != null && !this.selectedBeat.getVoice(getVoice()).isRestVoice()) {
222 			this.selectedBeat.getVoice(getVoice()).getDuration().copy(this.selectedDuration);
223 		}
224 	}
225 
moveUp()226 	public void moveUp() {
227 		int stringCount = this.selectedTrack.stringCount() ;
228 		int nextString = (( (this.string - 2 + stringCount) % stringCount) + 1);
229 		setStringNumber(nextString);
230 	}
231 
moveDown()232 	public void moveDown() {
233 		int stringCount = this.selectedTrack.stringCount() ;
234 		int nextString = ( (this.string  % stringCount) + 1);
235 		setStringNumber(nextString);
236 	}
237 
setStringNumber(int number)238 	public void setStringNumber(int number){
239 		this.string = number;
240 		this.updateNote();
241 	}
242 
getStringNumber()243 	public int getStringNumber(){
244 		return this.string;
245 	}
246 
getPosition()247 	public long getPosition() {
248 		return this.position;
249 	}
250 
getMeasure()251 	public TGMeasureImpl getMeasure() {
252 		return this.selectedMeasure;
253 	}
254 
getTrack()255 	public TGTrackImpl getTrack() {
256 		return this.selectedTrack;
257 	}
258 
getDuration()259 	public TGDuration getDuration() {
260 		return this.selectedDuration;
261 	}
262 
setSelectedDuration(TGDuration selectedDuration)263 	public void setSelectedDuration(TGDuration selectedDuration) {
264 		this.selectedDuration = selectedDuration;
265 	}
266 
getSelectedString()267 	public TGString getSelectedString() {
268 		List strings = this.selectedTrack.getStrings();
269 		Iterator it = strings.iterator();
270 		while (it.hasNext()) {
271 			TGString instrumentString = (TGString) it.next();
272 			if (instrumentString.getNumber() == this.string) {
273 				return instrumentString;
274 			}
275 		}
276 		return null;
277 	}
278 
changeDuration(TGDuration duration)279 	public void changeDuration(TGDuration duration){
280 		getSongManager().getMeasureManager().changeDuration(getMeasure(),getSelectedBeat(),duration,getVoice(), true);
281 		setChanges(true);
282 	}
283 
updatePosition()284 	private void updatePosition(){
285 		this.position = getSelectedBeat().getStart();
286 	}
287 
updateString()288 	private void updateString(){
289 		if(this.string < 1 || this.string > getTrack().stringCount() ){
290 			this.string = 1;
291 		}
292 	}
293 
checkTransport()294 	private void checkTransport(){
295 		TuxGuitar.instance().getTransport().gotoMeasure(getMeasure().getHeader());
296 	}
297 
hasChanges()298 	public boolean hasChanges() {
299 		return this.changes;
300 	}
301 
setChanges(boolean changes)302 	public void setChanges(boolean changes) {
303 		this.changes = changes;
304 	}
305 
getVelocity()306 	public int getVelocity() {
307 		return this.velocity;
308 	}
309 
setVelocity(int velocity)310 	public void setVelocity(int velocity) {
311 		this.velocity = velocity;
312 	}
313 
updateNote()314 	private void updateNote(){
315 		this.selectedNote = null;
316 
317 		TGString string = getSelectedString();
318 		if( string != null ){
319 			this.selectedNote = getSongManager().getMeasureManager().getNote(getMeasure(),getPosition(),string.getNumber());
320 		}
321 	}
322 
getSelectedNote()323 	public TGNote getSelectedNote(){
324 		return this.selectedNote;
325 	}
326 
updateBeat()327 	private void updateBeat(){
328 		this.restBeat = this.selectedBeat.isRestBeat();
329 	}
330 
getSelectedBeat()331 	public TGBeatImpl getSelectedBeat(){
332 		return (TGBeatImpl)this.selectedBeat;
333 	}
334 
getSongManager()335 	public TGSongManager getSongManager(){
336 		return this.tablature.getSongManager();
337 	}
338 
getVoice()339 	public int getVoice() {
340 		return this.voice;
341 	}
342 
setVoice(int voice)343 	public void setVoice(int voice) {
344 		this.voice = voice;
345 		this.update();
346 	}
347 
isRestBeatSelected()348 	public boolean isRestBeatSelected(){
349 		return this.restBeat;
350 	}
351 }