GUI: improve drag-and-drop, part 3

This commit is contained in:
tildearrow 2023-01-30 15:58:59 -05:00
parent 311c66ff9f
commit d1d92ac018
4 changed files with 57 additions and 98 deletions

View file

@ -386,10 +386,10 @@ void FurnaceGUI::doAction(int what) {
doSelectAll(); doSelectAll();
break; break;
case GUI_ACTION_PAT_CUT: case GUI_ACTION_PAT_CUT:
doCopy(true); doCopy(true,true,selStart,selEnd);
break; break;
case GUI_ACTION_PAT_COPY: case GUI_ACTION_PAT_COPY:
doCopy(false); doCopy(false,true,selStart,selEnd);
break; break;
case GUI_ACTION_PAT_PASTE: case GUI_ACTION_PAT_PASTE:
doPaste(); doPaste();

View file

@ -358,66 +358,75 @@ void FurnaceGUI::doTranspose(int amount, OperationMask& mask) {
makeUndo(GUI_UNDO_PATTERN_DELETE); makeUndo(GUI_UNDO_PATTERN_DELETE);
} }
void FurnaceGUI::doCopy(bool cut) { String FurnaceGUI::doCopy(bool cut, bool writeClipboard, const SelectionPoint& sStart, const SelectionPoint& sEnd) {
finishSelection(); if (writeClipboard) {
if (cut) { finishSelection();
curNibble=false; if (cut) {
prepareUndo(GUI_UNDO_PATTERN_CUT); curNibble=false;
prepareUndo(GUI_UNDO_PATTERN_CUT);
}
} }
clipboard=fmt::sprintf("org.tildearrow.furnace - Pattern Data (%d)\n%d",DIV_ENGINE_VERSION,selStart.xFine); String clipb=fmt::sprintf("org.tildearrow.furnace - Pattern Data (%d)\n%d",DIV_ENGINE_VERSION,sStart.xFine);
for (int j=selStart.y; j<=selEnd.y; j++) { for (int j=sStart.y; j<=sEnd.y; j++) {
int iCoarse=selStart.xCoarse; int iCoarse=sStart.xCoarse;
int iFine=selStart.xFine; int iFine=sStart.xFine;
if (iFine>3 && !(iFine&1)) { if (iFine>3 && !(iFine&1)) {
iFine--; iFine--;
} }
clipboard+='\n'; clipb+='\n';
for (; iCoarse<=selEnd.xCoarse; iCoarse++) { for (; iCoarse<=sEnd.xCoarse; iCoarse++) {
if (!e->curSubSong->chanShow[iCoarse]) continue; if (!e->curSubSong->chanShow[iCoarse]) continue;
DivPattern* pat=e->curPat[iCoarse].getPattern(e->curOrders->ord[iCoarse][curOrder],true); DivPattern* pat=e->curPat[iCoarse].getPattern(e->curOrders->ord[iCoarse][curOrder],true);
for (; iFine<3+e->curPat[iCoarse].effectCols*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) { for (; iFine<3+e->curPat[iCoarse].effectCols*2 && (iCoarse<sEnd.xCoarse || iFine<=sEnd.xFine); iFine++) {
if (iFine==0) { if (iFine==0) {
clipboard+=noteNameNormal(pat->data[j][0],pat->data[j][1]); clipb+=noteNameNormal(pat->data[j][0],pat->data[j][1]);
if (cut) { if (cut) {
pat->data[j][0]=0; pat->data[j][0]=0;
pat->data[j][1]=0; pat->data[j][1]=0;
} }
} else { } else {
if (pat->data[j][iFine+1]==-1) { if (pat->data[j][iFine+1]==-1) {
clipboard+=".."; clipb+="..";
} else { } else {
clipboard+=fmt::sprintf("%.2X",pat->data[j][iFine+1]); clipb+=fmt::sprintf("%.2X",pat->data[j][iFine+1]);
} }
if (cut) { if (cut) {
pat->data[j][iFine+1]=-1; pat->data[j][iFine+1]=-1;
} }
} }
} }
clipboard+='|'; clipb+='|';
iFine=0; iFine=0;
} }
} }
SDL_SetClipboardText(clipboard.c_str());
if (cut) { if (writeClipboard) {
makeUndo(GUI_UNDO_PATTERN_CUT); SDL_SetClipboardText(clipb.c_str());
if (cut) {
makeUndo(GUI_UNDO_PATTERN_CUT);
}
clipboard=clipb;
} }
return clipb;
} }
void FurnaceGUI::doPaste(PasteMode mode, int arg) { void FurnaceGUI::doPaste(PasteMode mode, int arg, bool readClipboard, String clipb) {
finishSelection(); if (readClipboard) {
prepareUndo(GUI_UNDO_PATTERN_PASTE); finishSelection();
char* clipText=SDL_GetClipboardText(); prepareUndo(GUI_UNDO_PATTERN_PASTE);
if (clipText!=NULL) { char* clipText=SDL_GetClipboardText();
if (clipText[0]) { if (clipText!=NULL) {
clipboard=clipText; if (clipText[0]) {
clipboard=clipText;
}
SDL_free(clipText);
} }
SDL_free(clipText); clipb=clipboard;
} }
std::vector<String> data; std::vector<String> data;
String tempS; String tempS;
for (char i: clipboard) { for (char i: clipb) {
if (i=='\r') continue; if (i=='\r') continue;
if (i=='\n') { if (i=='\n') {
data.push_back(tempS); data.push_back(tempS);
@ -562,15 +571,18 @@ void FurnaceGUI::doPaste(PasteMode mode, int arg) {
i=1; i=1;
} }
} }
if (settings.cursorPastePos) {
cursor.y=j;
if (cursor.y>=e->curSubSong->patLen) cursor.y=e->curSubSong->patLen-1;
selStart=cursor;
selEnd=cursor;
updateScroll(cursor.y);
}
makeUndo(GUI_UNDO_PATTERN_PASTE); if (readClipboard) {
if (settings.cursorPastePos) {
cursor.y=j;
if (cursor.y>=e->curSubSong->patLen) cursor.y=e->curSubSong->patLen-1;
selStart=cursor;
selEnd=cursor;
updateScroll(cursor.y);
}
makeUndo(GUI_UNDO_PATTERN_PASTE);
}
} }
void FurnaceGUI::doChangeIns(int ins) { void FurnaceGUI::doChangeIns(int ins) {
@ -926,72 +938,19 @@ void FurnaceGUI::doExpand(int multiplier) {
} }
void FurnaceGUI::doDrag() { void FurnaceGUI::doDrag() {
DivPattern* patBuffer=NULL;
int len=dragEnd.xCoarse-dragStart.xCoarse+1; int len=dragEnd.xCoarse-dragStart.xCoarse+1;
DETERMINE_FIRST_LAST;
if (len<1) return; if (len<1) return;
patBuffer=new DivPattern[len];
prepareUndo(GUI_UNDO_PATTERN_DRAG); prepareUndo(GUI_UNDO_PATTERN_DRAG);
// copy and clear // copy and clear
{ String c=doCopy(true,false,dragStart,dragEnd);
int iCoarse=dragStart.xCoarse;
int iFine=dragStart.xFine;
int iCoarseP=0;
for (; iCoarse<=dragEnd.xCoarse; iCoarse++) {
if (!e->curSubSong->chanShow[iCoarse]) continue;
DivPattern* pat=e->curPat[iCoarse].getPattern(e->curOrders->ord[iCoarse][curOrder],true);
for (; iFine<3+e->curPat[iCoarse].effectCols*2 && (iCoarse<dragEnd.xCoarse || iFine<=dragEnd.xFine); iFine++) {
int row=0;
for (int j=dragStart.y; j<=dragEnd.y; j++) {
if (iFine==0) {
patBuffer[iCoarseP].data[row][iFine]=pat->data[j][iFine];
pat->data[j][iFine]=0;
if (dragStart.y==dragEnd.y) pat->data[j][2]=-1;
}
patBuffer[iCoarseP].data[row][iFine+1]=pat->data[j][iFine+1];
pat->data[j][iFine+1]=(iFine<1)?0:-1;
if (dragStart.y==dragEnd.y && iFine>2 && iFine&1 && settings.effectDeletionAltersValue) {
pat->data[j][iFine+2]=-1;
}
row++;
}
}
iFine=0;
iCoarseP++;
}
}
// replace // replace
{ cursor=selStart;
int iCoarse=selStart.xCoarse; doPaste(GUI_PASTE_MODE_NORMAL,0,false,c);
int iFine=selStart.xFine;
int iCoarseP=0;
for (; iCoarse<=selEnd.xCoarse && iCoarseP<len; iCoarse++) {
if (iCoarse<firstChannel || iCoarse>lastChannel) continue;
if (!e->curSubSong->chanShow[iCoarse]) continue;
DivPattern* pat=e->curPat[iCoarse].getPattern(e->curOrders->ord[iCoarse][curOrder],true);
for (; iFine<3+e->curPat[iCoarse].effectCols*2 && (iCoarse<selEnd.xCoarse || iFine<=selEnd.xFine); iFine++) {
int row=-1;
for (int j=selStart.y; j<=selEnd.y; j++) {
row++;
if (j<0 || j>=e->curSubSong->patLen) continue;
if (iFine==0) {
pat->data[j][iFine]=patBuffer[iCoarseP].data[row][iFine];
}
pat->data[j][iFine+1]=patBuffer[iCoarseP].data[row][iFine+1];
}
}
iFine=0;
iCoarseP++;
}
}
delete[] patBuffer;
makeUndo(GUI_UNDO_PATTERN_DRAG); makeUndo(GUI_UNDO_PATTERN_DRAG);
} }

View file

@ -2303,8 +2303,8 @@ void FurnaceGUI::editOptions(bool topMenu) {
char id[4096]; char id[4096];
editOptsVisible=true; editOptsVisible=true;
if (ImGui::MenuItem("cut",BIND_FOR(GUI_ACTION_PAT_CUT))) doCopy(true); if (ImGui::MenuItem("cut",BIND_FOR(GUI_ACTION_PAT_CUT))) doCopy(true,true,selStart,selEnd);
if (ImGui::MenuItem("copy",BIND_FOR(GUI_ACTION_PAT_COPY))) doCopy(false); if (ImGui::MenuItem("copy",BIND_FOR(GUI_ACTION_PAT_COPY))) doCopy(false,true,selStart,selEnd);
if (ImGui::MenuItem("paste",BIND_FOR(GUI_ACTION_PAT_PASTE))) doPaste(); if (ImGui::MenuItem("paste",BIND_FOR(GUI_ACTION_PAT_PASTE))) doPaste();
if (ImGui::BeginMenu("paste special...")) { if (ImGui::BeginMenu("paste special...")) {
if (ImGui::MenuItem("paste mix",BIND_FOR(GUI_ACTION_PAT_PASTE_MIX))) doPaste(GUI_PASTE_MODE_MIX_FG); if (ImGui::MenuItem("paste mix",BIND_FOR(GUI_ACTION_PAT_PASTE_MIX))) doPaste(GUI_PASTE_MODE_MIX_FG);

View file

@ -1889,8 +1889,8 @@ class FurnaceGUI {
void doPullDelete(); void doPullDelete();
void doInsert(); void doInsert();
void doTranspose(int amount, OperationMask& mask); void doTranspose(int amount, OperationMask& mask);
void doCopy(bool cut); String doCopy(bool cut, bool writeClipboard, const SelectionPoint& sStart, const SelectionPoint& sEnd);
void doPaste(PasteMode mode=GUI_PASTE_MODE_NORMAL, int arg=0); void doPaste(PasteMode mode=GUI_PASTE_MODE_NORMAL, int arg=0, bool readClipboard=true, String clipb="");
void doChangeIns(int ins); void doChangeIns(int ins);
void doInterpolate(); void doInterpolate();
void doFade(int p0, int p1, bool mode); void doFade(int p0, int p1, bool mode);