diff -r a74f2ff353b8 -r b376645315ab src/actions/EditActions.cc
--- a/src/actions/EditActions.cc Wed Mar 12 16:20:40 2014 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,836 +0,0 @@
-/*
- * LDForge: LDasText parts authoring CAD
- * Copyright (C) 2013, 2014 Santeri Piippo
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include
-#include
-#include
-#include
-#include "../MainWindow.h"
-#include "../Main.h"
-#include "../Document.h"
-#include "../ColorSelector.h"
-#include "../Misc.h"
-#include "../Widgets.h"
-#include "../GLRenderer.h"
-#include "../Dialogs.h"
-#include "../Colors.h"
-#include "ui_replcoords.h"
-#include "ui_editraw.h"
-#include "ui_flip.h"
-#include "ui_addhistoryline.h"
-
-cfg (Bool, edit_schemanticinline, false);
-extern_cfg (String, ld_defaultuser);
-
-// =============================================================================
-//
-static int copyToClipboard()
-{
- LDObjectList objs = selection();
- int num = 0;
-
- // Clear the clipboard first.
- qApp->clipboard()->clear();
-
- // Now, copy the contents into the clipboard.
- QString data;
-
- for (LDObject* obj : objs)
- {
- if (data.length() > 0)
- data += "\n";
-
- data += obj->asText();
- ++num;
- }
-
- qApp->clipboard()->setText (data);
- return num;
-}
-
-// =============================================================================
-//
-DEFINE_ACTION (Cut, CTRL (X))
-{
- int num = copyToClipboard();
- deleteSelection();
- print (tr ("%1 objects cut"), num);
-}
-
-// =============================================================================
-//
-DEFINE_ACTION (Copy, CTRL (C))
-{
- int num = copyToClipboard();
- print (tr ("%1 objects copied"), num);
-}
-
-// =============================================================================
-//
-DEFINE_ACTION (Paste, CTRL (V))
-{
- const QString clipboardText = qApp->clipboard()->text();
- int idx = getInsertionPoint();
- getCurrentDocument()->clearSelection();
- int num = 0;
-
- for (QString line : clipboardText.split ("\n"))
- {
- LDObject* pasted = parseLine (line);
- getCurrentDocument()->insertObj (idx++, pasted);
- pasted->select();
- R()->compileObject (pasted);
- ++num;
- }
-
- print (tr ("%1 objects pasted"), num);
- refresh();
- scrollToSelection();
-}
-
-// =============================================================================
-//
-DEFINE_ACTION (Delete, KEY (Delete))
-{
- int num = deleteSelection();
- print (tr ("%1 objects deleted"), num);
-}
-
-// =============================================================================
-//
-static void doInline (bool deep)
-{
- LDObjectList sel = selection();
-
- for (LDObject* obj : sel)
- {
- // Get the index of the subfile so we know where to insert the
- // inlined contents.
- long idx = obj->lineNumber();
-
- if (idx == -1)
- continue;
-
- LDObjectList objs;
-
- if (obj->type() == LDObject::ESubfile)
- {
- LDSubfile::InlineFlags flags = deep ? LDSubfile::DeepCacheInline : LDSubfile::CacheInline;
- objs = static_cast (obj)->inlineContents (flags);
- }
- else
- continue;
-
- // Merge in the inlined objects
- for (LDObject* inlineobj : objs)
- {
- QString line = inlineobj->asText();
- inlineobj->destroy();
- LDObject* newobj = parseLine (line);
- getCurrentDocument()->insertObj (idx++, newobj);
- newobj->select();
- g_win->R()->compileObject (newobj);
- }
-
- // Delete the subfile now as it's been inlined.
- obj->destroy();
- }
-
- g_win->refresh();
-}
-
-DEFINE_ACTION (Inline, CTRL (I))
-{
- doInline (false);
-}
-
-DEFINE_ACTION (InlineDeep, CTRL_SHIFT (I))
-{
- doInline (true);
-}
-
-// =============================================================================
-//
-DEFINE_ACTION (SplitQuads, 0)
-{
- LDObjectList objs = selection();
- int num = 0;
-
- for (LDObject* obj : objs)
- {
- if (obj->type() != LDObject::EQuad)
- continue;
-
- // Find the index of this quad
- long index = obj->lineNumber();
-
- if (index == -1)
- return;
-
- QList triangles = static_cast (obj)->splitToTriangles();
-
- // Replace the quad with the first triangle and add the second triangle
- // after the first one.
- getCurrentDocument()->setObject (index, triangles[0]);
- getCurrentDocument()->insertObj (index + 1, triangles[1]);
-
- for (LDTriangle* t : triangles)
- R()->compileObject (t);
-
- // Delete this quad now, it has been split.
- obj->destroy();
-
- num++;
- }
-
- print ("%1 quadrilaterals split", num);
- refresh();
-}
-
-// =============================================================================
-//
-DEFINE_ACTION (EditRaw, KEY (F9))
-{
- if (selection().size() != 1)
- return;
-
- LDObject* obj = selection()[0];
- QDialog* dlg = new QDialog;
- Ui::EditRawUI ui;
-
- ui.setupUi (dlg);
- ui.code->setText (obj->asText());
-
- if (obj->type() == LDObject::EError)
- ui.errorDescription->setText (static_cast (obj)->reason());
- else
- {
- ui.errorDescription->hide();
- ui.errorIcon->hide();
- }
-
- if (!dlg->exec())
- return;
-
- LDObject* oldobj = obj;
-
- // Reinterpret it from the text of the input field
- obj = parseLine (ui.code->text());
- oldobj->replace (obj);
-
- // Refresh
- R()->compileObject (obj);
- refresh();
-}
-
-// =============================================================================
-//
-DEFINE_ACTION (SetColor, KEY (C))
-{
- if (selection().isEmpty())
- return;
-
- int colnum;
- int defcol = -1;
-
- LDObjectList objs = selection();
-
- // If all selected objects have the same color, said color is our default
- // value to the color selection dialog.
- defcol = getSelectedColor();
-
- // Show the dialog to the user now and ask for a color.
- if (ColorSelector::selectColor (colnum, defcol, g_win))
- {
- for (LDObject* obj : objs)
- {
- if (obj->isColored() == false)
- continue;
-
- obj->setColor (colnum);
- R()->compileObject (obj);
- }
-
- refresh();
- }
-}
-
-// =============================================================================
-//
-DEFINE_ACTION (Borders, CTRL_SHIFT (B))
-{
- LDObjectList objs = selection();
- int num = 0;
-
- for (LDObject* obj : objs)
- {
- const LDObject::Type type = obj->type();
- if (type != LDObject::EQuad && type != LDObject::ETriangle)
- continue;
-
- int numLines;
- LDLine* lines[4];
-
- if (type == LDObject::EQuad)
- {
- numLines = 4;
-
- LDQuad* quad = static_cast (obj);
- lines[0] = new LDLine (quad->vertex (0), quad->vertex (1));
- lines[1] = new LDLine (quad->vertex (1), quad->vertex (2));
- lines[2] = new LDLine (quad->vertex (2), quad->vertex (3));
- lines[3] = new LDLine (quad->vertex (3), quad->vertex (0));
- }
- else
- {
- numLines = 3;
-
- LDTriangle* tri = static_cast (obj);
- lines[0] = new LDLine (tri->vertex (0), tri->vertex (1));
- lines[1] = new LDLine (tri->vertex (1), tri->vertex (2));
- lines[2] = new LDLine (tri->vertex (2), tri->vertex (0));
- }
-
- for (int i = 0; i < numLines; ++i)
- {
- long idx = obj->lineNumber() + i + 1;
-
- lines[i]->setColor (edgecolor);
- getCurrentDocument()->insertObj (idx, lines[i]);
- R()->compileObject (lines[i]);
- }
-
- num += numLines;
- }
-
- print (tr ("Added %1 border lines"), num);
- refresh();
-}
-
-// =============================================================================
-//
-DEFINE_ACTION (CornerVerts, 0)
-{
- int num = 0;
-
- for (LDObject* obj : selection())
- {
- if (obj->vertices() < 2)
- continue;
-
- int ln = obj->lineNumber();
-
- for (int i = 0; i < obj->vertices(); ++i)
- {
- LDVertex* vert = new LDVertex;
- vert->pos = obj->vertex (i);
- vert->setColor (obj->color());
-
- getCurrentDocument()->insertObj (++ln, vert);
- R()->compileObject (vert);
- ++num;
- }
- }
-
- print (tr ("Added %1 vertices"), num);
- refresh();
-}
-
-// =============================================================================
-//
-static void doMoveSelection (const bool up)
-{
- LDObjectList objs = selection();
- LDObject::moveObjects (objs, up);
- g_win->buildObjList();
-}
-
-// =============================================================================
-//
-DEFINE_ACTION (MoveUp, KEY (PageUp))
-{
- doMoveSelection (true);
-}
-
-DEFINE_ACTION (MoveDown, KEY (PageDown))
-{
- doMoveSelection (false);
-}
-
-// =============================================================================
-//
-DEFINE_ACTION (Undo, CTRL (Z))
-{
- getCurrentDocument()->undo();
-}
-
-DEFINE_ACTION (Redo, CTRL_SHIFT (Z))
-{
- getCurrentDocument()->redo();
-}
-
-// =============================================================================
-//
-void doMoveObjects (Vertex vect)
-{
- // Apply the grid values
- vect[X] *= *currentGrid().confs[Grid::X];
- vect[Y] *= *currentGrid().confs[Grid::Y];
- vect[Z] *= *currentGrid().confs[Grid::Z];
-
- for (LDObject* obj : selection())
- {
- obj->move (vect);
- g_win->R()->compileObject (obj);
- }
-
- g_win->refresh();
-}
-
-// =============================================================================
-//
-DEFINE_ACTION (MoveXNeg, KEY (Left))
-{
- doMoveObjects ({ -1, 0, 0});
-}
-
-DEFINE_ACTION (MoveYNeg, KEY (Home))
-{
- doMoveObjects ({0, -1, 0});
-}
-
-DEFINE_ACTION (MoveZNeg, KEY (Down))
-{
- doMoveObjects ({0, 0, -1});
-}
-
-DEFINE_ACTION (MoveXPos, KEY (Right))
-{
- doMoveObjects ({1, 0, 0});
-}
-
-DEFINE_ACTION (MoveYPos, KEY (End))
-{
- doMoveObjects ({0, 1, 0});
-}
-
-DEFINE_ACTION (MoveZPos, KEY (Up))
-{
- doMoveObjects ({0, 0, 1});
-}
-
-// =============================================================================
-//
-DEFINE_ACTION (Invert, CTRL_SHIFT (W))
-{
- LDObjectList sel = selection();
-
- for (LDObject* obj : sel)
- {
- obj->invert();
- R()->compileObject (obj);
- }
-
- refresh();
-}
-
-// =============================================================================
-//
-static void rotateVertex (Vertex& v, const Vertex& rotpoint, const Matrix& transform)
-{
- v.move (-rotpoint);
- v.transform (transform, g_origin);
- v.move (rotpoint);
-}
-
-// =============================================================================
-//
-static void doRotate (const int l, const int m, const int n)
-{
- LDObjectList sel = selection();
- QList queue;
- const Vertex rotpoint = rotPoint (sel);
- const double angle = (pi * *currentGrid().confs[Grid::Angle]) / 180,
- cosangle = cos (angle),
- sinangle = sin (angle);
-
- // ref: http://en.wikipedia.org/wiki/Transformation_matrix#Rotation_2
- Matrix transform (
- {
- (l* l * (1 - cosangle)) + cosangle,
- (m* l * (1 - cosangle)) - (n* sinangle),
- (n* l * (1 - cosangle)) + (m* sinangle),
-
- (l* m * (1 - cosangle)) + (n* sinangle),
- (m* m * (1 - cosangle)) + cosangle,
- (n* m * (1 - cosangle)) - (l* sinangle),
-
- (l* n * (1 - cosangle)) - (m* sinangle),
- (m* n * (1 - cosangle)) + (l* sinangle),
- (n* n * (1 - cosangle)) + cosangle
- });
-
- // Apply the above matrix to everything
- for (LDObject* obj : sel)
- {
- if (obj->vertices())
- {
- for (int i = 0; i < obj->vertices(); ++i)
- {
- Vertex v = obj->vertex (i);
- rotateVertex (v, rotpoint, transform);
- obj->setVertex (i, v);
- }
- }
- elif (obj->hasMatrix())
- {
- LDMatrixObject* mo = dynamic_cast (obj);
-
- // Transform the position
- Vertex v = mo->position();
- rotateVertex (v, rotpoint, transform);
- mo->setPosition (v);
-
- // Transform the matrix
- mo->setTransform (transform * mo->transform());
- }
- elif (obj->type() == LDObject::EVertex)
- {
- LDVertex* vert = static_cast (obj);
- Vertex v = vert->pos;
- rotateVertex (v, rotpoint, transform);
- vert->pos = v;
- }
-
- g_win->R()->compileObject (obj);
- }
-
- g_win->refresh();
-}
-
-// =============================================================================
-//
-DEFINE_ACTION (RotateXPos, CTRL (Right))
-{
- doRotate (1, 0, 0);
-}
-DEFINE_ACTION (RotateYPos, CTRL (End))
-{
- doRotate (0, 1, 0);
-}
-DEFINE_ACTION (RotateZPos, CTRL (Up))
-{
- doRotate (0, 0, 1);
-}
-DEFINE_ACTION (RotateXNeg, CTRL (Left))
-{
- doRotate (-1, 0, 0);
-}
-DEFINE_ACTION (RotateYNeg, CTRL (Home))
-{
- doRotate (0, -1, 0);
-}
-DEFINE_ACTION (RotateZNeg, CTRL (Down))
-{
- doRotate (0, 0, -1);
-}
-
-DEFINE_ACTION (RotationPoint, (0))
-{
- configRotationPoint();
-}
-
-// =============================================================================
-//
-DEFINE_ACTION (RoundCoordinates, 0)
-{
- setlocale (LC_ALL, "C");
- int num = 0;
-
- for (LDObject* obj : selection())
- {
- LDMatrixObject* mo = dynamic_cast (obj);
-
- if (mo != null)
- {
- Vertex v = mo->position();
- Matrix t = mo->transform();
-
- for_axes (ax)
- roundToDecimals (v[ax], 3);
-
- // Let matrix values be rounded to 4 decimals,
- // they need that extra precision
- for (int i = 0; i < 9; ++i)
- roundToDecimals (t[i], 4);
-
- mo->setPosition (v);
- mo->setTransform (t);
- num += 10;
- }
- else
- {
- for (int i = 0; i < obj->vertices(); ++i)
- {
- Vertex v = obj->vertex (i);
-
- for_axes (ax)
- roundToDecimals (v[ax], 3);
-
- obj->setVertex (i, v);
- R()->compileObject (obj);
- num += 3;
- }
- }
- }
-
- print (tr ("Rounded %1 values"), num);
- refreshObjectList();
- refresh();
-}
-
-// =============================================================================
-//
-DEFINE_ACTION (Uncolorize, 0)
-{
- int num = 0;
-
- for (LDObject* obj : selection())
- {
- if (obj->isColored() == false)
- continue;
-
- int col = maincolor;
-
- if (obj->type() == LDObject::ELine || obj->type() == LDObject::ECondLine)
- col = edgecolor;
-
- obj->setColor (col);
- R()->compileObject (obj);
- num++;
- }
-
- print (tr ("%1 objects uncolored"), num);
- refresh();
-}
-
-// =============================================================================
-//
-DEFINE_ACTION (ReplaceCoords, CTRL (R))
-{
- QDialog* dlg = new QDialog (g_win);
- Ui::ReplaceCoordsUI ui;
- ui.setupUi (dlg);
-
- if (!dlg->exec())
- return;
-
- const double search = ui.search->value(),
- replacement = ui.replacement->value();
- const bool any = ui.any->isChecked(),
- rel = ui.relative->isChecked();
-
- QList sel;
- int num = 0;
-
- if (ui.x->isChecked()) sel << X;
- if (ui.y->isChecked()) sel << Y;
- if (ui.z->isChecked()) sel << Z;
-
- for (LDObject* obj : selection())
- {
- for (int i = 0; i < obj->vertices(); ++i)
- {
- Vertex v = obj->vertex (i);
-
- for (Axis ax : sel)
- {
- double& coord = v[ax];
-
- if (any || coord == search)
- {
- if (!rel)
- coord = 0;
-
- coord += replacement;
- num++;
- }
- }
-
- obj->setVertex (i, v);
- R()->compileObject (obj);
- }
- }
-
- print (tr ("Altered %1 values"), num);
- refresh();
-}
-
-// =============================================================================
-//
-DEFINE_ACTION (Flip, CTRL_SHIFT (F))
-{
- QDialog* dlg = new QDialog;
- Ui::FlipUI ui;
- ui.setupUi (dlg);
-
- if (!dlg->exec())
- return;
-
- QList sel;
-
- if (ui.x->isChecked()) sel << X;
- if (ui.y->isChecked()) sel << Y;
- if (ui.z->isChecked()) sel << Z;
-
- for (LDObject* obj : selection())
- {
- for (int i = 0; i < obj->vertices(); ++i)
- {
- Vertex v = obj->vertex (i);
-
- for (Axis ax : sel)
- v[ax] *= -1;
-
- obj->setVertex (i, v);
- R()->compileObject (obj);
- }
- }
-
- refresh();
-}
-
-// =============================================================================
-//
-DEFINE_ACTION (Demote, 0)
-{
- LDObjectList sel = selection();
- int num = 0;
-
- for (LDObject* obj : sel)
- {
- if (obj->type() != LDObject::ECondLine)
- continue;
-
- LDLine* repl = static_cast (obj)->demote();
- R()->compileObject (repl);
- ++num;
- }
-
- print (tr ("Demoted %1 conditional lines"), num);
- refresh();
-}
-
-// =============================================================================
-//
-static bool isColorUsed (int colnum)
-{
- for (LDObject* obj : getCurrentDocument()->objects())
- if (obj->isColored() && obj->color() == colnum)
- return true;
-
- return false;
-}
-
-// =============================================================================
-//
-DEFINE_ACTION (Autocolor, 0)
-{
- int colnum = 0;
-
- while (colnum < MAX_COLORS && (getColor (colnum) == null || isColorUsed (colnum)))
- colnum++;
-
- if (colnum >= MAX_COLORS)
- {
- print (tr ("Cannot auto-color: all colors are in use!"));
- return;
- }
-
- for (LDObject* obj : selection())
- {
- if (obj->isColored() == false)
- continue;
-
- obj->setColor (colnum);
- R()->compileObject (obj);
- }
-
- print (tr ("Auto-colored: new color is [%1] %2"), colnum, getColor (colnum)->name);
- refresh();
-}
-
-// =============================================================================
-//
-DEFINE_ACTION (AddHistoryLine, 0)
-{
- LDObject* obj;
- bool ishistory = false,
- prevIsHistory = false;
-
- QDialog* dlg = new QDialog;
- Ui_AddHistoryLine* ui = new Ui_AddHistoryLine;
- ui->setupUi (dlg);
- ui->m_username->setText (ld_defaultuser);
- ui->m_date->setDate (QDate::currentDate());
- ui->m_comment->setFocus();
-
- if (!dlg->exec())
- return;
-
- // Create the comment object based on input
- QString commentText = format ("!HISTORY %1 [%2] %3",
- ui->m_date->date().toString ("yyyy-MM-dd"),
- ui->m_username->text(),
- ui->m_comment->text());
-
- LDComment* comm = new LDComment (commentText);
-
- // Find a spot to place the new comment
- for (
- obj = getCurrentDocument()->getObject (0);
- obj && obj->next() && !obj->next()->isScemantic();
- obj = obj->next()
- )
- {
- LDComment* comm = dynamic_cast (obj);
-
- if (comm != null && comm->text().startsWith ("!HISTORY "))
- ishistory = true;
-
- if (prevIsHistory && !ishistory)
- {
- // Last line was history, this isn't, thus insert the new history
- // line here.
- break;
- }
-
- prevIsHistory = ishistory;
- }
-
- int idx = obj ? obj->lineNumber() : 0;
- getCurrentDocument()->insertObj (idx++, comm);
-
- // If we're adding a history line right before a scemantic object, pad it
- // an empty line
- if (obj && obj->next() && obj->next()->isScemantic())
- getCurrentDocument()->insertObj (idx, new LDEmpty);
-
- buildObjList();
- delete ui;
-}