package org.herac.tuxguitar.gui.editors.tab; import org.herac.tuxguitar.gui.TuxGuitar; import org.herac.tuxguitar.gui.editors.TGPainter; import org.herac.tuxguitar.gui.editors.tab.layout.ViewLayout; import org.herac.tuxguitar.gui.editors.tab.painters.TGNotePainter; import org.herac.tuxguitar.gui.editors.tab.painters.TGSilencePainter; import org.herac.tuxguitar.song.models.Clef; import org.herac.tuxguitar.song.models.Direction; import org.herac.tuxguitar.song.models.TGDivisionType; import org.herac.tuxguitar.song.models.TGDuration; import org.herac.tuxguitar.song.models.TGNote; import org.herac.tuxguitar.song.models.TGVoice; public class TGVoiceImpl extends TGVoice { /** * Union a la izquierda */ public static final int JOINED_TYPE_LEFT = 3; /** * desviacion a la izquierda */ public static final int JOINED_TYPE_NONE_LEFT = 1; /** * desviacion a la derecha */ public static final int JOINED_TYPE_NONE_RIGHT = 2; /** * Union a la derecha */ public static final int JOINED_TYPE_RIGHT = 4; private TGBeatGroup group; private boolean hiddenSilence; private TGVoiceImpl join1; private TGVoiceImpl join2; private boolean joinedGreaterThanQuarter; private int joinedType; private TGNoteImpl maxNote; private int maxString; private int maxY; private TGNoteImpl minNote; private int minString; private int minY; private TGVoiceImpl next; private TGVoiceImpl previous; private float silenceHeight; private float silenceY; private boolean[] usedStrings; private int width; public TGVoiceImpl(int index) { super(index); } public void check(TGNoteImpl note) { int value = note.getRealValue(); if (this.maxNote == null || value > this.maxNote.getRealValue()) { this.maxNote = note; } if (this.minNote == null || value < this.minNote.getRealValue()) { this.minNote = note; } this.getUsedStrings(); this.usedStrings[note.getString() - 1] = true; if (note.getString() > this.maxString) { this.maxString = note.getString(); } if (note.getString() < this.minString) { this.minString = note.getString(); } } public TGBeatGroup getBeatGroup() { return this.group; } public TGBeatImpl getBeatImpl() { return (TGBeatImpl) getBeat(); } public TGVoiceImpl getJoin1() { return this.join1; } public TGVoiceImpl getJoin2() { return this.join2; } public int getJoinedType() { return this.joinedType; } public TGNoteImpl getMaxNote() { return this.maxNote; } public int getMaxString() { return this.maxString; } public int getMaxY() { return this.maxY; } public TGMeasureImpl getMeasureImpl() { return (TGMeasureImpl) getBeat().getMeasure(); } public TGNoteImpl getMinNote() { return this.minNote; } public int getMinString() { return this.minString; } public int getMinY() { return this.minY; } public int getPaintPosition(int index) { return getMeasureImpl().getTs().getPosition(index); } public int getPosX() { return this.getBeatImpl().getPosX(); } public boolean[] getUsedStrings() { if (this.usedStrings == null) { this.usedStrings = new boolean[getBeat().getMeasure().getTrack() .stringCount()]; } return this.usedStrings; } public int getWidth() { return this.width; } public boolean isHiddenSilence() { return this.hiddenSilence; } public boolean isJoinedGreaterThanQuarter() { return this.joinedGreaterThanQuarter; } public boolean isPlaying(ViewLayout layout) { return (getMeasureImpl().isPlaying(layout) && TuxGuitar.instance() .getEditorCache().isPlaying(getBeat().getMeasure(), getBeat())); } public void paint(ViewLayout layout, TGPainter painter, int fromX, int fromY) { if (!isEmpty()) { if (isRestVoice() && !isHiddenSilence()) { paintSilence(layout, painter, fromX, fromY); } else { for (final TGNote note : getNotes()) { ((TGNoteImpl) note).paint(layout, painter, fromX, fromY); } if (!layout.isPlayModeEnabled()) { paintBeat(layout, painter, fromX, fromY); } } } } public void paintBeat(ViewLayout layout, TGPainter painter, int fromX, int fromY) { if (!isRestVoice()) { int style = layout.getStyle(); int spacing = getBeatImpl().getSpacing(); if ((style & ViewLayout.DISPLAY_SCORE) != 0) { paintScoreBeat(layout, painter, fromX, fromY + getPaintPosition(TGTrackSpacing.POSITION_SCORE_MIDDLE_LINES), spacing); } if ((style & ViewLayout.DISPLAY_TABLATURE) != 0 && (style & ViewLayout.DISPLAY_SCORE) == 0) { paintTablatureBeat(layout, painter, fromX, fromY + getPaintPosition(TGTrackSpacing.POSITION_TABLATURE), spacing); } } } public void paintDot(ViewLayout layout, TGPainter painter, float fromX, float fromY, float scale) { float dotSize = (3.0f * scale); float posX = fromX; float posY = fromY; layout.setDotStyle(painter); painter.initPath(TGPainter.PATH_FILL); painter.moveTo(posX - (dotSize / 2), posY - (dotSize / 2)); painter.addOval(posX - (dotSize / 2), posY - (dotSize / 2), dotSize, dotSize); if (getDuration().isDoubleDotted()) { painter .moveTo(posX + (dotSize + 2) - (dotSize / 2), posY - (dotSize / 2)); painter.addOval(posX + (dotSize + 2) - (dotSize / 2), posY - (dotSize / 2), dotSize, dotSize); } painter.closePath(); } public void paintScoreBeat(ViewLayout layout, TGPainter painter, int fromX, int fromY, int spacing) { int vX = (fromX + getPosX() + spacing); // division type if (!getDuration().getDivision().isEqual(TGDivisionType.NORMAL)) { layout.setDivisionTypeStyle(painter); painter .drawString( Integer.toString(getDuration().getDivision().getEnters()), vX, ((fromY - getPaintPosition(TGTrackSpacing.POSITION_SCORE_MIDDLE_LINES)) + getPaintPosition(TGTrackSpacing.POSITION_DIVISION_TYPE))); } // dibujo el pie if (getDuration().getValue() >= TGDuration.HALF) { layout.setScoreNoteFooterStyle(painter); float scale = layout.getScale(); float lineSpacing = layout.getScoreLineSpacing(); Direction direction = this.group.getDirection(); int key = getBeat().getMeasure().getKeySignature(); Clef clef = getBeat().getMeasure().getClef(); int xMove = (direction == Direction.UP ? layout.getResources() .getScoreNoteWidth() : 0); int yMove = (direction == Direction.UP ? ((layout.getScoreLineSpacing() / 3) + 1) : ((layout.getScoreLineSpacing() / 3) * 2)); int vY1 = fromY + (direction == Direction.DOWN ? this.maxNote.getScorePosY() : this.minNote.getScorePosY()); int vY2 = fromY + this.group.getY2(layout, getPosX() + spacing, key, clef); painter.initPath(); painter.setAntialias(false); painter.moveTo(vX + xMove, vY1 + yMove); painter.lineTo(vX + xMove, vY2); painter.closePath(); if (getDuration().getValue() >= TGDuration.EIGHTH) { int index = (getDuration().getIndex() - 3); if (index >= 0) { int dir = (direction == Direction.DOWN) ? 1 : -1; int joinedType = getJoinedType(); boolean joinedGreaterThanQuarter = isJoinedGreaterThanQuarter(); if ((joinedType == TGVoiceImpl.JOINED_TYPE_NONE_LEFT || joinedType == TGVoiceImpl.JOINED_TYPE_NONE_RIGHT) && !joinedGreaterThanQuarter) { float hX = (fromX + xMove + getPosX() + spacing); float hY = ((fromY + this.group.getY2(layout, getPosX() + spacing, key, clef)) - ((lineSpacing * 2) * dir)); for (int i = 0; i <= index; i++) { painter.initPath(TGPainter.PATH_FILL); TGNotePainter.paintFooter(painter, hX, (hY - ((i * (lineSpacing / 2.0f)) * dir)), dir, lineSpacing); painter.closePath(); } } else { int hX1 = 0; int hX2 = 0; if (joinedType == TGVoiceImpl.JOINED_TYPE_NONE_RIGHT) { hX1 = getPosX() + spacing; hX2 = getPosX() + spacing + 6; } else if (joinedType == TGVoiceImpl.JOINED_TYPE_NONE_LEFT) { hX1 = getPosX() + spacing - 5; hX2 = getPosX() + spacing; } else { hX1 = getJoin1().getPosX() + getJoin1().getBeatImpl().getSpacing(); hX2 = getJoin2().getPosX() + getJoin2().getBeatImpl().getSpacing(); } int hY1 = fromY + this.group.getY2(layout, hX1, key, clef); int hY2 = fromY + this.group.getY2(layout, hX2, key, clef); painter.setLineWidth(Math.max(1, Math.round(3f * scale))); painter.initPath(); for (int i = 0; i <= index; i++) { painter.moveTo(fromX + xMove + hX1, hY1 - ((i * (5f * scale)) * dir)); painter.lineTo(fromX + xMove + hX2, hY2 - ((i * (5f * scale)) * dir)); } painter.closePath(); painter.setLineWidth(1); } } } } } // ----silence public void paintSilence(ViewLayout layout, TGPainter painter, int fromX, int fromY) { int style = layout.getStyle(); int x = 0; int lineSpacing = 0; float y = 0; float scale = 0; if ((style & ViewLayout.DISPLAY_SCORE) != 0) { x = fromX + getPosX() + getBeatImpl().getSpacing(); y = fromY + getPaintPosition(TGTrackSpacing.POSITION_SCORE_MIDDLE_LINES) + this.silenceY; lineSpacing = layout.getScoreLineSpacing(); scale = (lineSpacing / 9.0f); } else { x = fromX + getPosX() + getBeatImpl().getSpacing() - 1; y = fromY + getPaintPosition(TGTrackSpacing.POSITION_TABLATURE) + this.silenceY; lineSpacing = layout.getStringSpacing(); scale = (lineSpacing / 10.0f); } setStyle(layout, painter, (layout.isPlayModeEnabled() && isPlaying(layout))); painter.initPath(TGPainter.PATH_FILL); int duration = getDuration().getValue(); if (duration == TGDuration.WHOLE) { TGSilencePainter.paintWhole(painter, x, y, scale); } else if (duration == TGDuration.HALF) { TGSilencePainter.paintHalf(painter, x, y, scale); } else if (duration == TGDuration.QUARTER) { TGSilencePainter.paintQuarter(painter, x, y, scale); } else if (duration == TGDuration.EIGHTH) { TGSilencePainter.paintEighth(painter, x, y, scale); } else if (duration == TGDuration.SIXTEENTH) { TGSilencePainter.paintSixteenth(painter, x, y, scale); } else if (duration == TGDuration.THIRTY_SECOND) { TGSilencePainter.paintThirtySecond(painter, x, y, scale); } else if (duration == TGDuration.SIXTY_FOURTH) { TGSilencePainter.paintSixtyFourth(painter, x, y, scale); } painter.closePath(); if (getDuration().isDotted() || getDuration().isDoubleDotted()) { layout.setDotStyle(painter); painter.initPath(); painter.moveTo(x + 10, y + 1); painter.addOval(x + 10, y + 1, 1, 1); if (getDuration().isDoubleDotted()) { painter.moveTo(x + 13, y + 1); painter.addOval(x + 13, y + 1, 1, 1); } painter.closePath(); } if (!getDuration().getDivision().isEqual(TGDivisionType.NORMAL)) { layout.setDivisionTypeStyle(painter); if ((style & ViewLayout.DISPLAY_SCORE) != 0) { painter.drawString(Integer.toString(getDuration().getDivision() .getEnters()), x, (fromY + getPaintPosition(TGTrackSpacing.POSITION_DIVISION_TYPE))); } else { painter.drawString(Integer.toString(getDuration().getDivision() .getEnters()), x, (fromY + getPaintPosition(TGTrackSpacing.POSITION_DIVISION_TYPE))); } } } public void paintTablatureBeat(ViewLayout layout, TGPainter painter, int fromX, int fromY, int spacing) { if (!isRestVoice()) { float scale = layout.getScale(); float xMove = (2 * scale); float x = (fromX + getPosX() + spacing + xMove); float y1 = 0; float y2 = 0; float verticalLineWidth = scale; float horizontalLineWidth = (2 * scale); int stringSpacing = layout.getStringSpacing(); if (getBeatGroup().getDirection() == Direction.DOWN) { y1 = (fromY + getMeasureImpl().getTrackImpl().getTabHeight() + (stringSpacing / 2)); y2 = (fromY + getMeasureImpl().getTrackImpl().getTabHeight() + ((stringSpacing / 2) * 5)); } else { y1 = (fromY - (stringSpacing / 2) - horizontalLineWidth); y2 = (fromY - ((stringSpacing / 2) * 5)); } if (getDuration().getValue() >= TGDuration.QUARTER) { layout.setTabNoteFooterStyle(painter); painter.initPath(); painter.setAntialias(false); painter.setLineWidth((int) verticalLineWidth); painter.moveTo(x, y1); painter.lineTo(x, y2); painter.closePath(); if (getDuration().getValue() >= TGDuration.EIGHTH) { float x1 = 0; float x2 = 0; int joinedType = getJoinedType(); if (joinedType == TGVoiceImpl.JOINED_TYPE_NONE_RIGHT) { x1 = getPosX() + xMove + spacing; x2 = getPosX() + xMove + spacing + (6 * scale); } else if (joinedType == TGVoiceImpl.JOINED_TYPE_NONE_LEFT) { x1 = getPosX() + xMove + spacing - (5 * scale); x2 = getPosX() + xMove + spacing; } else { x1 = getJoin1().getPosX() + xMove + getJoin1().getBeatImpl().getSpacing(); x2 = getJoin2().getPosX() + xMove + getJoin2().getBeatImpl().getSpacing(); } int index = (getDuration().getIndex() - 2); if (index > 0) { int height = (layout.getStringSpacing() / 2); int direction = (getBeatGroup().getDirection() == Direction.DOWN ? 1 : -1); painter.setLineWidth((int) horizontalLineWidth); painter.initPath(); for (int i = index; i > 0; i--) { painter.moveTo(fromX + x1, y2 + ((height - (i * height)) * direction)); painter.lineTo(fromX + x2, y2 + ((height - (i * height)) * direction)); } painter.closePath(); painter.setLineWidth(1); } } } else if (getDuration().getValue() == TGDuration.HALF) { layout.setTabNoteFooterStyle(painter); painter.initPath(); painter.setAntialias(false); painter.setLineWidth((int) verticalLineWidth); painter.moveTo(x, (y1 + ((y2 - y1) / 2))); painter.lineTo(x, y2); painter.closePath(); } // -------------puntillo-------------------------------------- if (getDuration().isDotted() || getDuration().isDoubleDotted()) { int joinedType = getJoinedType(); float posX = ((getDuration().getValue() > TGDuration.WHOLE) ? ((joinedType == TGVoiceImpl.JOINED_TYPE_NONE_RIGHT || joinedType == TGVoiceImpl.JOINED_TYPE_RIGHT) ? (x + (4.0f * scale)) : (x - (5.0f * scale))) : x); float posY = (y2 - ((getDuration().getValue() >= TGDuration.EIGHTH) ? ((stringSpacing / 2) * (getDuration() .getIndex() - 2)) : (1.0f * scale))); paintDot(layout, painter, posX, posY, scale); } // -------------tresillo-------------------------------------- if (!getDuration().getDivision().isEqual(TGDivisionType.NORMAL)) { layout.setDivisionTypeStyle(painter); painter .drawString( Integer.toString(getDuration().getDivision().getEnters()), (int) (x - 3), ((fromY - getPaintPosition(TGTrackSpacing.POSITION_TABLATURE)) + getPaintPosition(TGTrackSpacing.POSITION_DIVISION_TYPE))); } } } public void reset() { this.maxNote = null; this.minNote = null; this.hiddenSilence = false; this.usedStrings = new boolean[getBeat().getMeasure().getTrack() .stringCount()]; this.maxString = 1; this.minString = getBeat().getMeasure().getTrack().stringCount(); this.group = null; this.previous = null; this.next = null; } public void setBeatGroup(TGBeatGroup group) { this.group = group; } public void setHiddenSilence(boolean hiddenSilence) { this.hiddenSilence = hiddenSilence; } public void setJoin1(TGVoiceImpl join1) { this.join1 = join1; } public void setJoin2(TGVoiceImpl join2) { this.join2 = join2; } public void setJoinedGreaterThanQuarter(boolean joinedGreaterThanQuarter) { this.joinedGreaterThanQuarter = joinedGreaterThanQuarter; } public void setJoinedType(int joinedType) { this.joinedType = joinedType; } public void setNextBeat(TGVoiceImpl next) { this.next = next; } public void setPreviousBeat(TGVoiceImpl previous) { this.previous = previous; } public void setStyle(ViewLayout layout, TGPainter painter, boolean playMode) { if ((layout.getStyle() & ViewLayout.DISPLAY_SCORE) != 0) { layout.setScoreSilenceStyle(painter, playMode); } else { layout.setTabSilenceStyle(painter, playMode); } } public void setWidth(int width) { this.width = width; } public void update(ViewLayout layout) { this.minY = 0; this.maxY = 0; if (isRestVoice()) { this.updateSilenceSpacing(layout); } else { this.updateNoteVoice(layout); } } public void updateNoteVoice(ViewLayout layout) { this.joinedType = JOINED_TYPE_NONE_RIGHT; this.joinedGreaterThanQuarter = false; this.setJoin1(this); this.setJoin2(this); boolean noteJoined = false; boolean withPrev = false; // trato de unir con el componente anterior if (this.previous != null && !this.previous.isRestVoice()) { if (getMeasureImpl() .canJoin(layout.getSongManager(), this, this.previous)) { withPrev = true; if (this.previous.getDuration().getValue() >= getDuration().getValue()) { this.setJoin1(this.previous); this.setJoin2(this); this.joinedType = JOINED_TYPE_LEFT; noteJoined = true; } if (this.previous.getDuration().getValue() > TGDuration.QUARTER) { this.joinedGreaterThanQuarter = true; } } } // trato de unir con el componente que le sigue if (this.next != null && !this.next.isRestVoice()) { if (getMeasureImpl().canJoin(layout.getSongManager(), this, this.next)) { if (this.next.getDuration().getValue() >= getDuration().getValue()) { this.setJoin2(this.next); if (this.previous == null || this.previous.isRestVoice() || this.previous.getDuration().getValue() < getDuration() .getValue()) { this.setJoin1(this); } noteJoined = true; this.joinedType = JOINED_TYPE_RIGHT; } if (this.next.getDuration().getValue() > TGDuration.QUARTER) { this.joinedGreaterThanQuarter = true; } } } // si no hubo union decido para que lado girar la figura if (!noteJoined && withPrev) { this.joinedType = JOINED_TYPE_NONE_LEFT; } if ((layout.getStyle() & ViewLayout.DISPLAY_TABLATURE) != 0 && (layout.getStyle() & ViewLayout.DISPLAY_SCORE) == 0) { this.minY = 0; this.maxY = getBeatImpl().getMeasureImpl().getTrackImpl().getTabHeight(); if (getBeatGroup().getDirection() == Direction.DOWN) { this.maxY += (((layout.getStringSpacing() / 2) * 5) + 1); } else { this.minY -= (((layout.getStringSpacing() / 2) * 5) + 1); } } } public void updateSilenceSpacing(ViewLayout layout) { this.silenceY = 0; this.silenceHeight = 0; if (!isHiddenSilence()) { int style = layout.getStyle(); int lineSpacing = 0; int lineCount = 0; float scale = 0; if ((style & ViewLayout.DISPLAY_SCORE) != 0) { lineSpacing = layout.getScoreLineSpacing(); lineCount = 5; scale = (lineSpacing / 9.0f); } else { lineSpacing = layout.getStringSpacing(); lineCount = getBeat().getMeasure().getTrack().stringCount(); scale = (lineSpacing / 10.0f); } int duration = getDuration().getValue(); if (duration == TGDuration.WHOLE) { this.silenceHeight = (scale * 3.6513581f); this.silenceY = (lineCount <= 5 ? lineSpacing : lineSpacing * 2); } else if (duration == TGDuration.HALF) { this.silenceHeight = (scale * 3.6513581f); this.silenceY = (lineCount <= 5 ? lineSpacing * 2 : lineSpacing * 3) - this.silenceHeight; } else if (duration == TGDuration.QUARTER) { this.silenceHeight = (scale * 16); this.silenceY = ((lineSpacing * (lineCount - 1)) / 2) - (this.silenceHeight / 2); } else if (duration == TGDuration.EIGHTH) { this.silenceHeight = (scale * 12); this.silenceY = ((lineSpacing * (lineCount - 1)) / 2) - (this.silenceHeight / 2); } else if (duration == TGDuration.SIXTEENTH) { this.silenceHeight = (scale * 16); this.silenceY = ((lineSpacing * (lineCount - 1)) / 2) - (this.silenceHeight / 2); } else if (duration == TGDuration.THIRTY_SECOND) { this.silenceHeight = (scale * 24); this.silenceY = ((lineSpacing * (lineCount - 1)) / 2) - (this.silenceHeight / 2); } else if (duration == TGDuration.SIXTY_FOURTH) { this.silenceHeight = (scale * 28); this.silenceY = ((lineSpacing * (lineCount - 1)) / 2) - (this.silenceHeight / 2); } for (int v = 0; v < getBeat().countVoices(); v++) { if (v != getIndex()) { TGVoiceImpl voice = getBeatImpl().getVoiceImpl(v); if (!voice.isEmpty()) { if (voice.isRestVoice()) { if (!voice.isHiddenSilence()) { float maxSilenceHeight = (lineSpacing * 3); float firstPosition = (this.silenceY - (maxSilenceHeight / getBeat() .countVoices())); this.silenceY = (firstPosition + (maxSilenceHeight * getIndex())); } } else if ((layout.getStyle() & ViewLayout.DISPLAY_SCORE) != 0) { Direction direction = voice.getBeatGroup().getDirection(); int y1 = voice.getBeatGroup().getY1(layout, voice.getMinNote(), getMeasureImpl().getKeySignature(), getMeasureImpl().getClef()); int y2 = voice.getBeatGroup().getY1(layout, voice.getMaxNote(), getMeasureImpl().getKeySignature(), getMeasureImpl().getClef()); if (direction == Direction.UP) { float position = (y1 + (lineSpacing * 2)); if (position > this.silenceY) { this.silenceY = position; } } else if (direction == Direction.DOWN) { float position = (y2 - (this.silenceHeight + lineSpacing)); if (position < this.silenceY) { this.silenceY = position; } } } else if ((layout.getStyle() & ViewLayout.DISPLAY_TABLATURE) != 0) { Direction direction = voice.getBeatGroup().getDirection(); if (direction == Direction.UP) { float position = (lineSpacing * voice.getMaxString()); if (position > this.silenceY) { this.silenceY = position; } } else if (direction == Direction.DOWN) { float position = ((lineSpacing * (voice.getMinString() - 1)) - (this.silenceHeight + lineSpacing)); if (position < this.silenceY) { this.silenceY = position; } } } } } } this.minY = (int) this.silenceY; this.maxY = (int) (this.silenceY + this.silenceHeight); } } }