X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fapplicationwindow.cpp;h=773146fa63348865180b5159d56e0e785231313f;hb=9bf789d643e1885fee526a1d4d1e2648f02bbd86;hp=a4c39b74fe96eace7ee7376055641138c6c49d1e;hpb=e78daf62eb771ee29a59035d16cf63c1e6ebe144;p=architektonas diff --git a/src/applicationwindow.cpp b/src/applicationwindow.cpp index a4c39b7..773146f 100644 --- a/src/applicationwindow.cpp +++ b/src/applicationwindow.cpp @@ -37,6 +37,7 @@ #include "layerwidget.h" #include "objectwidget.h" #include "painter.h" +#include "penwidget.h" #include "settingsdialog.h" #include "structs.h" #include "utils.h" @@ -86,7 +87,7 @@ ApplicationWindow::ApplicationWindow(): dock3->setObjectName("Object"); // Create status bar - zoomIndicator = new QLabel("Grid: 12.0\" BU: Inch"); + zoomIndicator = new QLabel("Zoom: 100% Grid: 12.0\" BU: Inch"); statusBar()->addPermanentWidget(zoomIndicator); statusBar()->showMessage(tr("Ready")); @@ -97,8 +98,10 @@ ApplicationWindow::ApplicationWindow(): connect(lw, SIGNAL(LayerDeleted(int)), drawing, SLOT(DeleteCurrentLayer(int))); connect(lw, SIGNAL(LayerToggled()), drawing, SLOT(HandleLayerToggle())); connect(lw, SIGNAL(LayersSwapped(int, int)), drawing, SLOT(HandleLayerSwap(int, int))); + connect(this, SIGNAL(ReloadLayers()), lw, SLOT(Reload())); connect(drawing, SIGNAL(ObjectHovered(Object *)), ow, SLOT(ShowInfo(Object *))); + connect(drawing, SIGNAL(NeedZoomUpdate()), this, SLOT(UpdateZoom())); } @@ -112,9 +115,38 @@ void ApplicationWindow::closeEvent(QCloseEvent * event) void ApplicationWindow::FileNew(void) { - // Should warn the user if drawing hasn't been saved... !!! FIX !!! + // Warn the user if drawing has changed and hasn't been saved... + if (drawing->dirty) + { + QMessageBox msg; + + msg.setText("The document has been modified."); + msg.setInformativeText("Do you want to save your changes?"); + msg.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); + msg.setDefaultButton(QMessageBox::Save); + int response = msg.exec(); + + switch (response) + { + case QMessageBox::Save: + // Save was clicked + FileSave(); + break; + case QMessageBox::Discard: + // Don't Save was clicked + break; + case QMessageBox::Cancel: + // Cancel was clicked + return; +// break; + } + } + + FileIO::ResetLayerVectors(); + emit ReloadLayers(); DeleteContents(drawing->document.objects); drawing->document.objects.clear(); + drawing->dirty = false; drawing->update(); documentName.clear(); setWindowTitle("Architektonas - Untitled"); @@ -142,7 +174,7 @@ void ApplicationWindow::FileOpen(void) return; } - Container container; + Container container(true); // Make sure it's a top level container... bool successful = FileIO::LoadAtnsFile(file, &container); fclose(file); @@ -160,9 +192,12 @@ void ApplicationWindow::FileOpen(void) //printf("FileOpen: container size = %li\n", container.objects.size()); // Keep memory leaks from happening by getting rid of the old document DeleteContents(drawing->document.objects); + emit ReloadLayers(); // We can do this because the vector is just a bunch of pointers to our - // Objects, and the Containers (non-empty) can be moved way with no problem. + // Objects, and the Containers (non-empty) can be moved this way with no + // problem. drawing->document = container; + drawing->dirty = false; drawing->update(); documentName = filename; setWindowTitle(QString("Architektonas - %1").arg(documentName)); @@ -203,6 +238,7 @@ void ApplicationWindow::FileSave(void) return; } + drawing->dirty = false; setWindowTitle(QString("Architektonas - %1").arg(documentName)); statusBar()->showMessage(tr("Drawing saved.")); } @@ -221,6 +257,16 @@ void ApplicationWindow::FileSaveAs(void) } +void ApplicationWindow::contextMenuEvent(QContextMenuEvent * event) +{ + QMenu menu(this); + menu.addAction(mirrorAct); + menu.addAction(rotateAct); + menu.addAction(trimAct); + menu.exec(event->globalPos()); +} + + void ApplicationWindow::SnapToGridTool(void) { Global::snapToGrid = snapToGridAct->isChecked(); @@ -340,78 +386,68 @@ void ApplicationWindow::AddSplineTool(void) void ApplicationWindow::ZoomInTool(void) { - double zoomFactor = 2.0; -/* -We need to find the center of the screen, then figure out where the new corner -will be in the zoomed in window. - -So we know in Qt coords, the center is found via: -size.width() / 2 --> xCenter -size.height() / 2 --> yCenter - -transform x/yCenter to Cartesian coordinates. So far, so good. - -when zooming in, new origin will be (xCenter - origin.x) / 2, (yCenter - origin.y) / 2 -(after subtracting from center, that is...) -*/ + double zoomFactor = 1.20; QSize size = drawing->size(); - Vector center(size.width() / 2.0, size.height() / 2.0); -//printf("Zoom in... Center=%.2f,%.2f; ", center.x, center.y); - center = Painter::QtToCartesianCoords(center); -//printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y); - Vector newOrigin = center - ((center - Global::origin) / zoomFactor); -//printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y); - Global::origin = newOrigin; - -//printf("Zoom in... level going from %02f to ", Painter::zoom); - // This just zooms leaving origin intact... should zoom in at the current - // center! [DONE] + Vector center = Painter::QtToCartesianCoords(Vector(size.width() / 2.0, size.height() / 2.0)); + + Global::origin = center - ((center - Global::origin) / zoomFactor); Global::zoom *= zoomFactor; - Global::gridSpacing = drawing->gridPixels / Global::zoom; - drawing->UpdateGridBackground(); - drawing->update(); - zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(Global::gridSpacing)); - baseUnitInput->setText(QString("%1").arg(Global::gridSpacing)); + UpdateZoom(); } void ApplicationWindow::ZoomOutTool(void) { -/* -Ok, real example. -center = (436, 311) -origin = (223, 160.5) -newOrigin should be (-10, -10) -Why isn't it? - -center - origin = (213, 150.5) -origin - center = (-213, -150.5) -x 2 = (-426, -301) -+ center = (-10, -10) - -*/ - double zoomFactor = 2.0; + double zoomFactor = 1.20; QSize size = drawing->size(); - Vector center(size.width() / 2.0, size.height() / 2.0); -//printf("Zoom out... Center=%.2f,%.2f; ", center.x, center.y); - center = Painter::QtToCartesianCoords(center); -//printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y); -// Vector newOrigin = (center - Painter::origin) * zoomFactor; -// Vector newOrigin = center - (Painter::origin * zoomFactor); - Vector newOrigin = center + ((Global::origin - center) * zoomFactor); -//printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y); - Global::origin = newOrigin; -//printf("Zoom out...\n"); - // This just zooms leaving origin intact... should zoom out at the current - // center! [DONE] + Vector center = Painter::QtToCartesianCoords(Vector(size.width() / 2.0, size.height() / 2.0)); + + Global::origin = center + ((Global::origin - center) * zoomFactor); Global::zoom /= zoomFactor; - Global::gridSpacing = drawing->gridPixels / Global::zoom; - drawing->UpdateGridBackground(); + + UpdateZoom(); +} + + +void ApplicationWindow::UpdateZoom(void) +{ + // And now, a bunch of heuristics to select the right grid size--autogrid! + // :-P + if (Global::zoom < 0.25) + Global::gridSpacing = 48.0; + else if (Global::zoom >= 0.25 && Global::zoom < 0.50) + Global::gridSpacing = 36.0; + else if (Global::zoom >= 0.50 && Global::zoom < 1.00) + Global::gridSpacing = 24.0; + else if (Global::zoom >= 1.00 && Global::zoom < 2.00) + Global::gridSpacing = 12.0; + else if (Global::zoom >= 2.00 && Global::zoom < 4.00) + Global::gridSpacing = 6.0; + else if (Global::zoom >= 4.00 && Global::zoom < 8.00) + Global::gridSpacing = 3.0; + else if (Global::zoom >= 8.00 && Global::zoom < 16.00) + Global::gridSpacing = 1.0; + else if (Global::zoom >= 16.00 && Global::zoom < 32.00) + Global::gridSpacing = 0.5; + else if (Global::zoom >= 32.00 && Global::zoom < 64.00) + Global::gridSpacing = 0.25; + else if (Global::zoom >= 64.00 && Global::zoom < 128.00) + Global::gridSpacing = 0.125; + else if (Global::zoom >= 128.00 && Global::zoom < 256.00) + Global::gridSpacing = 0.0625; + else if (Global::zoom >= 256.00 && Global::zoom < 512.00) + Global::gridSpacing = 0.03125; + else + Global::gridSpacing = 0.015625; + + drawing->SetGridSize((double)(Global::gridSpacing * Global::zoom)); drawing->update(); - zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(Global::gridSpacing)); - baseUnitInput->setText(QString("%1").arg(Global::gridSpacing)); + zoomIndicator->setText(QString("Zoom: %1% Grid: %2\" BU: Inch").arg(Global::zoom * 100.0).arg(Global::gridSpacing)); + + // This is the problem... Changing this causes the state to update itself again, screwing up the origin... !!! FIX !!! (commented out for now) +// baseUnitInput->setText(QString("%1").arg(Global::gridSpacing)); } @@ -419,7 +455,8 @@ void ApplicationWindow::ClearUIToolStatesExcept(QAction * exception) { QAction * actionList[] = { addArcAct, addLineAct, addCircleAct, addDimensionAct, addPolygonAct, - addSplineAct, deleteAct, rotateAct, mirrorAct, trimAct, triangulateAct, 0 + addSplineAct, deleteAct, rotateAct, mirrorAct, trimAct, + triangulateAct, 0 }; for(int i=0; actionList[i]!=0; i++) @@ -492,57 +529,6 @@ void ApplicationWindow::Settings(void) // void ApplicationWindow::HandleGrouping(void) { -#if 0 - int itemsSelected = drawing->document.ItemsSelected(); - - // If nothing selected, do nothing - if (itemsSelected == 0) - { - statusBar()->showMessage(tr("No objects selected to make a group from.")); - return; - } - - // If it's a group that's selected, ungroup it and leave the objects in a - // selected state - if (itemsSelected == 1) - { - Object * object = drawing->document.SelectedItem(0); - -#if 0 -if (object == NULL) - printf("SelectedItem = NULL!\n"); -else - printf("SelectedItem = %08X, type = %i\n", object, object->type); -#endif - - if (object == NULL || object->type != OTContainer) - { - statusBar()->showMessage(tr("A group requires two or more selected objects.")); - return; - } - - // Need the parent of the group, we're assuming here that the parent is - // the drawing's document. Does it matter? Maybe... - // Could just stipulate that grouping like this only takes place where - // the parent of the group is the drawing's document. Makes life much - // simpler. - ((Container *)object)->SelectAll(); - ((Container *)object)->MoveContentsTo(&(drawing->document)); - drawing->document.Delete(object); - statusBar()->showMessage(tr("Objects ungrouped.")); - } - // Otherwise, if it's a group of 2 or more objects (which can be groups too) - // group them and select the group - else if (itemsSelected > 1) - { - Container * container = new Container(Vector(), &(drawing->document)); - drawing->document.MoveSelectedContentsTo(container); - drawing->document.Add(container); - container->DeselectAll(); - container->state = OSSelected; - statusBar()->showMessage(QString(tr("Grouped %1 objects.")).arg(itemsSelected)); - } -#else int numSelected = drawing->select.size(); // If nothing selected, do nothing @@ -569,13 +555,8 @@ else // Could just stipulate that grouping like this only takes place where // the parent of the group is the drawing's document. Makes life much // simpler. -// ((Container *)object)->SelectAll(); -// ((Container *)object)->MoveContentsTo(&(drawing->document)); -// drawing->document.Delete(object); Container * c = (Container *)obj; -//printf("Ungroup: container size = %li\n", c->objects.size()); SelectAll(c->objects); -//printf("Ungroup: document size = %li (pre-AddObjectsTo)\n", drawing->document.objects.size()); RemoveSelectedObjects(drawing->document.objects); AddObjectsTo(drawing->document.objects, c->objects); drawing->select.clear(); @@ -588,26 +569,22 @@ else // group them and select the group else if (numSelected > 1) { -// Container * container = new Container(Vector(), &(drawing->document)); -// drawing->document.MoveSelectedContentsTo(container); -// drawing->document.Add(container); -// container->DeselectAll(); -// container->state = OSSelected; - Container * c = new Container(); -// AddObjectsTo(c->objects, drawing->select); -// RemoveSelectedObjects(drawing->document.objects); MoveSelectedObjectsTo(c->objects, drawing->document.objects); drawing->document.objects.push_back(c); ClearSelected(c->objects); c->selected = true; - c->layer = Global::currentLayer; + c->layer = Global::activeLayer; + + Rect r = drawing->GetObjectExtents((Object *)c); + c->p[0] = r.TopLeft(); + c->p[1] = r.BottomRight(); + drawing->select.clear(); drawing->select.push_back(c); statusBar()->showMessage(QString(tr("Grouped %1 objects.")).arg(numSelected)); //printf("Group: document size = %li\n", drawing->document.objects.size()); } -#endif drawing->update(); } @@ -690,7 +667,7 @@ void ApplicationWindow::HandleDisconnection(void) void ApplicationWindow::HandleGridSizeInPixels(int size) { - drawing->SetGridSize(size); + drawing->SetGridSize((uint32_t)size); drawing->update(); } @@ -716,6 +693,9 @@ void ApplicationWindow::HandleGridSizeInBaseUnits(QString text) void ApplicationWindow::HandleDimensionSize(QString text) { +/* +This is the third input on the view toolbar; not sure what it was supposed to do... (resize all dimensions in the drawing?) +*/ // Parse the text... bool ok; double value = text.toDouble(&ok); @@ -728,6 +708,51 @@ void ApplicationWindow::HandleDimensionSize(QString text) drawing->update(); } +void ApplicationWindow::EditCopy(void) +{ + if (drawing->select.size() > 0) + { + DeleteContents(clipboard); + clipboard = CopySelectedObjects(drawing->document.objects); + } +} + + +void ApplicationWindow::EditCut(void) +{ + if (drawing->select.size() > 0) + { + DeleteContents(clipboard); + clipboard = MoveSelectedObjectsFrom(drawing->document.objects); + drawing->update(); + } +} + + +void ApplicationWindow::EditPaste(void) +{ + if (clipboard.size() > 0) + { + // We want to maybe make it so that the pasted objects are being moved in a "mouse drag" state... + ClearSelected(drawing->document.objects); + SelectAll(clipboard); + drawing->document.Add(CopyObjects(clipboard)); + drawing->update(); + } +} + + +// +// Select all *visible* objects. If an object is on a layer that is not +// visible, skip it. +// +void ApplicationWindow::SelectAllObjects(void) +{ + // Set object's state & update the drawing + SelectAll(drawing->document.objects); + drawing->update(); +} + void ApplicationWindow::CreateActions(void) { @@ -814,6 +839,17 @@ void ApplicationWindow::CreateActions(void) triangulateAct = CreateAction(tr("&Triangulate"), tr("Triangulate"), tr("Make triangles from selected lines, preserving their lengths."), QIcon(":/res/triangulate-tool.png"), QKeySequence("t,g"), true); connect(triangulateAct, SIGNAL(triggered()), this, SLOT(TriangulateTool())); + editCutAct = CreateAction(tr("&Cut Objects"), tr("Cut Objects"), tr("Cut objects from the drawing to the clipboard."), QIcon(":/res/editcut2.png"), QKeySequence(tr("Ctrl+x"))); + connect(editCutAct, SIGNAL(triggered()), this, SLOT(EditCut())); + + editCopyAct = CreateAction(tr("&Copy Objects"), tr("Copy Objects"), tr("Copy objects from the drawing to the clipboard."), QIcon(":/res/editcopy2.png"), QKeySequence(tr("Ctrl+c"))); + connect(editCopyAct, SIGNAL(triggered()), this, SLOT(EditCopy())); + + editPasteAct = CreateAction(tr("&Paste Objects"), tr("Paste Objects"), tr("Paste objects from the clipboard to the drawing."), QIcon(":/res/editpaste2.png"), QKeySequence(tr("Ctrl+v"))); + connect(editPasteAct, SIGNAL(triggered()), this, SLOT(EditPaste())); + + selectAllAct = CreateAction(tr("Select &All"), tr("Select All Objects"), tr("Select all objects in the drawing."), QIcon(), QKeySequence(tr("Ctrl+a"))); + connect(selectAllAct, SIGNAL(triggered()), this, SLOT(SelectAllObjects())); //Hm. I think we'll have to have separate logic to do the "Radio Group Toolbar" thing... // Yup, in order to turn them off, we'd have to have an "OFF" toolbar button. Ick. @@ -829,8 +865,8 @@ void ApplicationWindow::CreateActions(void) // // Consolidates action creation from a multi-step process to a single-step one. // -QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip, - QIcon icon, QKeySequence key, bool checkable/*= false*/) +QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, + QString statustip, QIcon icon, QKeySequence key, bool checkable/*= false*/) { QAction * action = new QAction(icon, name, this); action->setToolTip(tooltip); @@ -846,8 +882,9 @@ QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString // This is essentially the same as the previous function, but this allows more // than one key sequence to be added as key shortcuts. // -QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip, - QIcon icon, QKeySequence key1, QKeySequence key2, bool checkable/*= false*/) +QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, + QString statustip, QIcon icon, QKeySequence key1, QKeySequence key2, + bool checkable/*= false*/) { QAction * action = new QAction(icon, name, this); action->setToolTip(tooltip); @@ -889,6 +926,10 @@ void ApplicationWindow::CreateMenus(void) menu->addAction(connectAct); menu->addAction(disconnectAct); menu->addSeparator(); + menu->addAction(selectAllAct); + menu->addAction(editCutAct); + menu->addAction(editCopyAct); + menu->addAction(editPasteAct); menu->addAction(deleteAct); menu->addSeparator(); menu->addAction(addLineAct); @@ -937,6 +978,9 @@ void ApplicationWindow::CreateToolbars(void) toolbar->addAction(mirrorAct); toolbar->addAction(trimAct); toolbar->addAction(triangulateAct); + toolbar->addAction(editCutAct); + toolbar->addAction(editCopyAct); + toolbar->addAction(editPasteAct); toolbar->addAction(deleteAct); toolbar->addAction(connectAct); toolbar->addAction(disconnectAct); @@ -954,6 +998,16 @@ void ApplicationWindow::CreateToolbars(void) connect(spinbox, SIGNAL(valueChanged(int)), this, SLOT(HandleGridSizeInPixels(int))); connect(baseUnitInput, SIGNAL(textChanged(QString)), this, SLOT(HandleGridSizeInBaseUnits(QString))); connect(dimensionSizeInput, SIGNAL(textChanged(QString)), this, SLOT(HandleDimensionSize(QString))); + + PenWidget * pw = new PenWidget(); + toolbar = addToolBar(tr("Pen")); + toolbar->setObjectName(tr("Pen")); + toolbar->addWidget(pw); + connect(drawing, SIGNAL(ObjectSelected(Object *)), pw, SLOT(SetFields(Object *))); + connect(pw, SIGNAL(WidthSelected(float)), drawing, SLOT(HandlePenWidth(float))); + connect(pw, SIGNAL(StyleSelected(int)), drawing, SLOT(HandlePenStyle(int))); + connect(pw, SIGNAL(ColorSelected(uint32_t)), drawing, SLOT(HandlePenColor(uint32_t))); + connect(pw, SIGNAL(StampSelected(void)), drawing, SLOT(HandlePenStamp(void))); }