From 7d7631bc9d22166bd6e6e802615b1b259c9454cf Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 10 Dec 2011 21:36:02 +0000 Subject: [PATCH] + add task panel for projections (j-dowsett) git-svn-id: https://free-cad.svn.sourceforge.net/svnroot/free-cad/trunk@5262 e8eeb9e2-ec13-0410-a4a9-efa5cf37419d --- src/Mod/Drawing/Gui/CMakeLists.txt | 20 + src/Mod/Drawing/Gui/Command.cpp | 50 +- src/Mod/Drawing/Gui/Makefile.am | 5 + src/Mod/Drawing/Gui/Resources/Drawing.qrc | 1 + src/Mod/Drawing/Gui/Resources/Makefile.am | 1 + src/Mod/Drawing/Gui/TaskOrthoViews.cpp | 827 ++++++++++++++++++++++ src/Mod/Drawing/Gui/TaskOrthoViews.h | 157 ++++ src/Mod/Drawing/Gui/TaskOrthoViews.ui | 379 ++++++++++ src/Mod/Drawing/Gui/Workbench.cpp | 3 + 9 files changed, 1438 insertions(+), 5 deletions(-) create mode 100644 src/Mod/Drawing/Gui/TaskOrthoViews.cpp create mode 100644 src/Mod/Drawing/Gui/TaskOrthoViews.h create mode 100644 src/Mod/Drawing/Gui/TaskOrthoViews.ui diff --git a/src/Mod/Drawing/Gui/CMakeLists.txt b/src/Mod/Drawing/Gui/CMakeLists.txt index 6ceed491b..b8f41c034 100644 --- a/src/Mod/Drawing/Gui/CMakeLists.txt +++ b/src/Mod/Drawing/Gui/CMakeLists.txt @@ -5,6 +5,7 @@ else(MSVC) endif(MSVC) include_directories( + ${CMAKE_SOURCE_DIR}/src ${CMAKE_CURRENT_BINARY_DIR} ${Boost_INCLUDE_DIRS} ${COIN3D_INCLUDE_DIR} @@ -22,16 +23,27 @@ set(DrawingGui_LIBS FreeCADGui ) + set(DrawingGui_MOC_HDRS DrawingView.h + TaskOrthoViews.h TaskDialog.h ) + + + fc_wrap_cpp(DrawingGui_MOC_SRCS ${DrawingGui_MOC_HDRS}) SOURCE_GROUP("Moc" FILES ${DrawingGui_MOC_SRCS}) qt4_add_resources(DrawingGui_SRCS Resources/Drawing.qrc) +set(DrawingGui_UIC_SRCS + TaskOrthoViews.ui +) + +qt4_wrap_ui(DrawingGui_UIC_HDRS ${DrawingGui_UIC_SRCS}) + SET(DrawingGui_SRCS ${DrawingGui_SRCS} AppDrawingGui.cpp @@ -42,6 +54,9 @@ SET(DrawingGui_SRCS PreCompiled.h TaskDialog.cpp TaskDialog.h + TaskOrthoViews.ui + TaskOrthoViews.cpp + TaskOrthoViews.h Workbench.cpp Workbench.h ) @@ -60,6 +75,11 @@ SOURCE_GROUP("Mod" FILES ${DrawingGui_SRCS}) SOURCE_GROUP("SVG-View" FILES ${DrawingGuiView_SRCS}) SOURCE_GROUP("ViewProvider" FILES ${DrawingGuiViewProvider_SRCS}) +SET(DrawingGuiTaskDlgs_SRCS + TaskOrthoViews.ui +) +SOURCE_GROUP("TaskDialogs" FILES ${DrawingGuiTaskDlgs_SRCS}) + if(MSVC) add_definitions(-D_PreComp_) GET_MSVC_PRECOMPILED_SOURCE("PreCompiled.cpp" PCH_SRCS ${DrawingGui_SRCS} ${DrawingGuiView_SRCS} ${DrawingGuiViewProvider_SRCS}) diff --git a/src/Mod/Drawing/Gui/Command.cpp b/src/Mod/Drawing/Gui/Command.cpp index a1fb737ee..053648197 100644 --- a/src/Mod/Drawing/Gui/Command.cpp +++ b/src/Mod/Drawing/Gui/Command.cpp @@ -5,7 +5,7 @@ * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * for detail see the LICENCE text file. * - * Jürgen Riegel 2002 * + * Jürgen Riegel 2002 * * * ***************************************************************************/ @@ -31,6 +31,7 @@ #include "DrawingView.h" #include "TaskDialog.h" +#include "TaskOrthoViews.h" using namespace DrawingGui; using namespace std; @@ -86,14 +87,14 @@ CmdDrawingNewPage::CmdDrawingNewPage() } void CmdDrawingNewPage::activated(int iMsg) -{ +{ std::string FeatName = getUniqueObjectName("Page"); if (iMsg == 3) { openCommand("Drawing create page"); doCommand(Doc,"App.activeDocument().addObject('Drawing::FeaturePage','%s')",FeatName.c_str()); doCommand(Doc,"App.activeDocument().%s.Template = 'A3_Landscape.svg'",FeatName.c_str()); - commitCommand(); + commitCommand(); } else { QMessageBox::critical(Gui::getMainWindow(), @@ -203,13 +204,13 @@ CmdDrawingNewA3Landscape::CmdDrawingNewA3Landscape() } void CmdDrawingNewA3Landscape::activated(int iMsg) -{ +{ std::string FeatName = getUniqueObjectName("Page"); openCommand("Drawing create page"); doCommand(Doc,"App.activeDocument().addObject('Drawing::FeaturePage','%s')",FeatName.c_str()); doCommand(Doc,"App.activeDocument().%s.Template = 'A3_Landscape.svg'",FeatName.c_str()); - commitCommand(); + commitCommand(); } bool CmdDrawingNewA3Landscape::isActive(void) @@ -272,6 +273,44 @@ void CmdDrawingNewView::activated(int iMsg) commitCommand(); } +//=========================================================================== +// Drawing_OrthoView +//=========================================================================== + +DEF_STD_CMD(CmdDrawingOrthoViews); + +CmdDrawingOrthoViews::CmdDrawingOrthoViews() + : Command("Drawing_OrthoViews") +{ + sAppModule = "Drawing"; + sGroup = QT_TR_NOOP("Drawing"); + sMenuText = QT_TR_NOOP("Insert orthographic views"); + sToolTipText = QT_TR_NOOP("Insert an orthographic projection of a part in the active drawing"); + sWhatsThis = "Drawing_OrthoView"; + sStatusTip = sToolTipText; + sPixmap = "actions/drawing-orthoviews"; +} + +void CmdDrawingOrthoViews::activated(int iMsg) +{ + std::vector shapes = getSelection().getObjectsOfType(Part::Feature::getClassTypeId()); + if (shapes.size() != 1) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select a Part object.")); + return; + } + + std::vector pages = this->getDocument()->getObjectsOfType(Drawing::FeaturePage::getClassTypeId()); + if (pages.empty()){ + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("No page to insert"), + QObject::tr("Create a page to insert views into.")); + return; + } + + Gui::Control().showDialog(new TaskDlgOrthoViews()); +} + + //=========================================================================== // Drawing_ExportPage //=========================================================================== @@ -366,6 +405,7 @@ void CreateDrawingCommands(void) rcCmdMgr.addCommand(new CmdDrawingNewPage()); rcCmdMgr.addCommand(new CmdDrawingNewA3Landscape()); rcCmdMgr.addCommand(new CmdDrawingNewView()); + rcCmdMgr.addCommand(new CmdDrawingOrthoViews()); rcCmdMgr.addCommand(new CmdDrawingExportPage()); rcCmdMgr.addCommand(new CmdDrawingProjectShape()); } diff --git a/src/Mod/Drawing/Gui/Makefile.am b/src/Mod/Drawing/Gui/Makefile.am index 7d962cd49..2ecb17db5 100644 --- a/src/Mod/Drawing/Gui/Makefile.am +++ b/src/Mod/Drawing/Gui/Makefile.am @@ -4,8 +4,13 @@ lib_LTLIBRARIES=libDrawingGui.la DrawingGui.la BUILT_SOURCES=\ moc_DrawingView.cpp \ + moc_TaskOrthoViews.h \ + ui_TaskOrthoViews.h \ moc_TaskDialog.cpp +libDrawingGui_la_UI=\ + TaskOrthoViews.ui + libDrawingGui_la_SOURCES=\ AppDrawingGuiPy.cpp \ Command.cpp \ diff --git a/src/Mod/Drawing/Gui/Resources/Drawing.qrc b/src/Mod/Drawing/Gui/Resources/Drawing.qrc index 32cc43d83..6eb1358e1 100644 --- a/src/Mod/Drawing/Gui/Resources/Drawing.qrc +++ b/src/Mod/Drawing/Gui/Resources/Drawing.qrc @@ -14,6 +14,7 @@ icons/actions/drawing-landscape.svg icons/actions/drawing-portrait-A4.svg icons/actions/drawing-view.svg + icons/actions/drawing-orthoviews.svg translations/Drawing_af.qm translations/Drawing_de.qm translations/Drawing_es.qm diff --git a/src/Mod/Drawing/Gui/Resources/Makefile.am b/src/Mod/Drawing/Gui/Resources/Makefile.am index 0964a5fb7..19f31fdb2 100644 --- a/src/Mod/Drawing/Gui/Resources/Makefile.am +++ b/src/Mod/Drawing/Gui/Resources/Makefile.am @@ -18,6 +18,7 @@ EXTRA_DIST = \ icons/actions/drawing-landscape-A4.svg \ icons/actions/drawing-landscape-new.svg \ icons/actions/drawing-portrait-A4.svg \ + icons/actions/drawing-orthoviews.svg \ icons/Page.svg \ icons/Pages.svg \ icons/View.svg \ diff --git a/src/Mod/Drawing/Gui/TaskOrthoViews.cpp b/src/Mod/Drawing/Gui/TaskOrthoViews.cpp new file mode 100644 index 000000000..a7b2083ec --- /dev/null +++ b/src/Mod/Drawing/Gui/TaskOrthoViews.cpp @@ -0,0 +1,827 @@ +/*************************************************************************** + * Copyright (c) 2011 Joe Dowsett * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" + +//#ifndef _PreComp_ +//# include +//#endif + +#include "TaskOrthoViews.h" +#include "ui_TaskOrthoViews.h" + +#include +#include +#include +#include +#include +#include + +using namespace Gui; +using namespace DrawingGui; +using namespace std; + + + +int name_to_number(QString nme) +{ + char * temp[] = {"","Front","Back","Right","Left","Top","Bottom"}; + for (int j=0; j < 7; j++) + { + if (QString::fromUtf8(temp[j]) == nme) + return j; + } + return 0; +} + +char * number_to_name(int j) +{ + char * temp[] = {"","Front","Back","Right","Left","Top","Bottom"}; + return temp[j]; +} + +void rotate_coords(float& x, float& y, int i) +{ + float temp[4][2] = + { + { x, y}, + {-y, x}, + {-x,-y}, + { y,-x} + }; + + float t1 = temp[i][0]; + float t2 = temp[i][1]; + x = t1; + y = t2; +} + + + + + +orthoView::orthoView(std::string name, const char * targetpage, const char * sourcepart, Base::BoundBox3d partbox) +{ + myname = name; + mybox = partbox; + + orientation = 0; + angle = 0; + pageX = 0; + pageY = 0; + scale = 1; + x = 0; + y = 0; + dir = 0; + angle = 0; + + Command::doCommand(Command::Doc,"App.activeDocument().addObject('Drawing::FeatureViewPart','%s')",myname.c_str()); + Command::doCommand(Command::Doc,"App.activeDocument().%s.Source = App.activeDocument().%s",myname.c_str(), sourcepart); + Command::doCommand(Command::Doc,"App.activeDocument().%s.addObject(App.activeDocument().%s)",targetpage,myname.c_str()); + + activate(false); +} + +orthoView::~orthoView() +{ +} + +void orthoView::deleteme() +{ + Command::doCommand(Command::Doc,"App.activeDocument().removeObject('%s')", myname.c_str()); +} + +void orthoView::activate(bool state) +{ + if (state) + { + active = true; + Command::doCommand(Command::Doc,"Gui.ActiveDocument.getObject('%s').Visibility = True", myname.c_str()); + //Visibility doesn't seem to work, workaround (to counter any problems caused by active = false workaround): + //setPos(); + } + else + { + active = false; + Command::doCommand(Command::Doc,"Gui.ActiveDocument.getObject('%s').Visibility = False", myname.c_str()); + //Visibility doesn't seem to work, workaround: + Command::doCommand(Command::Doc,"App.activeDocument().%s.X = -10000", myname.c_str()); + Command::doCommand(Command::Doc,"App.activeDocument().%s.Y = -10000", myname.c_str()); + dir = 0; + width = 0; + height = 0; + } +} + +void orthoView::setDir(int i) +{ + dir = i; + int vx = (dir == 3) - (dir == 4); + int vy = (dir == 1) - (dir == 2); + int vz = (dir == 5) - (dir == 6); + + //drawings default to funny orientations for each view, line below calculates rotation to correct this + //drawing will then be oriented correctly for it being primary view, setOrientation is used to modify this for secondary views. + angle = -90*vx - 90*vy + (vz == -1)*180; + + calcCentre(); + + if (active) + { + Command::doCommand(Command::Doc,"App.activeDocument().%s.Direction = (%d,%d,%d)",myname.c_str(),vx,vy,vz); + Command::doCommand(Command::Doc,"App.activeDocument().%s.Label = '%s'",myname.c_str(),number_to_name(i)); + } +} + +void orthoView::setPos(float px, float py) +{ + if (px != 0 && py !=0) + { + pageX = px; + pageY = py; + } + + float ox = pageX + x; + float oy = pageY + y; + + if (active) + { + Command::doCommand(Command::Doc,"App.activeDocument().%s.X = %f", myname.c_str(), ox); + Command::doCommand(Command::Doc,"App.activeDocument().%s.Y = %f", myname.c_str(), oy); + } +} + +void orthoView::setScale(float newScale) +{ + scale = newScale; + if (active) + Command::doCommand(Command::Doc,"App.activeDocument().%s.Scale = %f",myname.c_str(), scale); + calcCentre(); +} + +void orthoView::setOrientation(int orient) +{ + orientation = orient; + if (active) + Command::doCommand(Command::Doc,"App.activeDocument().%s.Rotation = %d", myname.c_str(), (90*orientation+angle)); + calcCentre(); +} + +void orthoView::calcCentre() +{ +//the drawing view 'Position' refers to where the part origin should be on the page +//we need to find the position of the centre of correct bounding box face relative to the part origin +//this depends upon: +// - which view (eg Front, Left, Top etc), given by 'dir' +// - the scale of the drawing, since eg centre.x is the absolute point, while x is the distance on page. +// - the orientation of the view on the page, will switch x/y as per a rotation. + + float cx = mybox.CalcCenter().x; + float cy = mybox.CalcCenter().y; + float cz = mybox.CalcCenter().z; + + float coords[7][2] = + { + {0, 0}, + {-cx, cz}, //front + { cx, cz}, //back + { cy, cz}, //right + {-cy, cz}, //left + {-cx, -cy}, //top + {-cx, cy} //bottom + }; + + x = coords[dir][0] * scale; + y = coords[dir][1] * scale; + rotate_coords(x,y,orientation); + + float dx = mybox.LengthX(); + float dy = mybox.LengthY(); + float dz = mybox.LengthZ(); + + float dims[4][2] = + { + { 0, 0}, //zero height/width for no direction + {dx, dz}, //front & back + {dy, dz}, //right & left + {dx, dy} //top & bottom + }; + + width = dims[(dir+1)/2][0]; + height = dims[(dir+1)/2][1]; + if (orientation % 2 == 1) + { + float temp = width; + width = height; + height = temp; + } +} + +void orthoView::hidden(int state) +{ + if (state == 2) + Command::doCommand(Command::Doc,"App.activeDocument().%s.ShowHiddenLines = True", myname.c_str()); + else + Command::doCommand(Command::Doc,"App.activeDocument().%s.ShowHiddenLines = False", myname.c_str()); +} + +void orthoView::smooth(int state) +{ + if (state == 2) + Command::doCommand(Command::Doc,"App.activeDocument().%s.ShowSmoothLines = True", myname.c_str()); + else + Command::doCommand(Command::Doc,"App.activeDocument().%s.ShowSmoothLines = False", myname.c_str()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + + +TaskOrthoViews::TaskOrthoViews(QWidget *parent) + : ui(new Ui_TaskOrthoViews) +{ + ui->setupUi(this); + + std::vector obj = Gui::Selection().getObjectsOfType(Part::Feature::getClassTypeId()); + Base::BoundBox3d bbox; + std::vector::iterator it = obj.begin(); + bbox.Add(static_cast(*it)->Shape.getBoundingBox()); + + const char * part = obj.front()->getNameInDocument(); + App::Document* doc = App::GetApplication().getActiveDocument(); + + std::vector pages = doc->getObjectsOfType(Drawing::FeaturePage::getClassTypeId()); + std::string PageName = pages.front()->getNameInDocument(); + const char * page = PageName.c_str(); + + std::string name1 = doc->getUniqueObjectName("Ortho").c_str(); + views[0] = new orthoView(name1, page, part, bbox); + name1 = doc->getUniqueObjectName("Ortho").c_str(); + views[1] = new orthoView(name1, page, part, bbox); + name1 = doc->getUniqueObjectName("Ortho").c_str(); + views[2] = new orthoView(name1, page, part, bbox); + + primary = 0; + secondary_1 = 0; + secondary_2 = 0; + rotate = 0; + proj = 1; + autoscale = 1; + + //these need to be calculated depending upon page size + margin = 10; + pagewidth = 400; + pageh1 = 277; + pageh2 = 217; + min_space = 15; + + //also need to be calculated, as default initial settings in case autoscale is deselected. + spacing_1 = 100; + spacing_2 = 100; + scale = 1; + x_pos = 150; + y_pos = 150; + + + connect(ui->projection, SIGNAL(currentIndexChanged(int)), this, SLOT(projectionChanged(int))); + connect(ui->rotate, SIGNAL(currentIndexChanged(int)), this, SLOT(setRotate(int))); + connect(ui->smooth, SIGNAL(stateChanged(int)), this, SLOT(smooth(int))); + connect(ui->hidden, SIGNAL(stateChanged(int)), this, SLOT(hidden(int))); + connect(ui->auto_tog, SIGNAL(stateChanged(int)), this, SLOT(toggle_auto(int))); + connect(ui->s1, SIGNAL(editingFinished()), this, SLOT(data_entered())); + connect(ui->s2, SIGNAL(editingFinished()), this, SLOT(data_entered())); + connect(ui->x, SIGNAL(editingFinished()), this, SLOT(data_entered())); + connect(ui->y, SIGNAL(editingFinished()), this, SLOT(data_entered())); + connect(ui->scale, SIGNAL(editingFinished()), this, SLOT(data_entered())); + connect(ui->primary, SIGNAL(activated(int)), this, SLOT(setPrimary(int))); + connect(ui->secondary_1, SIGNAL(activated(int)), this, SLOT(setSecondary_1(int))); + connect(ui->secondary_2, SIGNAL(activated(int)), this, SLOT(setSecondary_2(int))); + +//this matrix contains the relative positions of specified views in third angle projection. +//horizontal coord specifies the primary view, vertical coord specifies a secondary view +//but to retrieve, get transfrom[secondary][primary] +//then matrix contents {x,y,r} specifies directional x and y of secondary view relative to primary view (with y increasing downwards as per SVG +//r specifies rotation of view from default, eg 1 = 90 degrees clockwise. +// +//first angle can be obtained by taking -ve of x and y coords, no change of r is required. + + // primary view direction -> 1 2 3 4 5 6 + int temp[7][7][3] ={{{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}}, + /*secondary 1 */ {{0,0,0}, {0,0,0}, {0,0,0}, {-1,0,0}, {1,0,0}, {0,1,0}, {0,-1,0}}, + /*view 2 */ {{0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {-1,0,0}, {0,-1,2}, {0,1,2}}, + /*direction 3 */ {{0,0,0}, {1,0,0}, {-1,0,0}, {0,0,0}, {0,0,0}, {1,0,3}, {1,0,1}}, + /* 4 */ {{0,0,0}, {-1,0,0}, {1,0,0}, {0,0,0}, {0,0,0}, {-1,0,1}, {-1,0,3}}, + /* 5 */ {{0,0,0}, {0,-1,0}, {0,-1,2}, {0,-1,1}, {0,-1,3}, {0,0,0}, {0,0,0}}, + /* 6 */ {{0,0,0}, {0,1,0}, {0,1,2}, {0,1,3}, {0,1,1}, {0,0,0}, {0,0,0}}}; + + for (int i=0; i < 7; i++) + for (int j=0; j < 7; j++) + for (int k=0; k < 3; k++) //initialisation needs to be done this way (rather than initialise transform directly + transform[i][j][k] = temp[i][j][k]; //in order to avoid compiler warning + +// Command::doCommand(Command::Doc,"#%d", transform[6][3][2]); + +} //end of constructor + +TaskOrthoViews::~TaskOrthoViews() +{ + delete views[0]; + delete views[1]; + delete views[2]; + delete ui; +} + +void TaskOrthoViews::autodims(float s1_x, float s1_y, float s2_x, float s2_y) +{ + int num_wide = abs(s1_x) + abs(s2_x) + 2; //tells us how many 'spaces' there are in each direction + int num_high = abs(s1_y) + abs(s2_y) + 2; //eg if s1_x = 1, then 3 spaces, page_edge -> primary -> secondary -> page_edge + + //now calculate real (non-scaled) width/height of views when combined togethor + float width = views[0]->width; //dimensions of primary view + float height = views[0]->height; + width += (s1_x != 0) * views[1]->width; //only add width if secondary view is alongside primary (ie s1_x <> 0) + height += (s1_y != 0) * views[1]->height; //equivalently for height + width += (s2_x != 0) * views[2]->width; + height += (s2_y != 0) * views[2]->height; + + int pageheight; //allow extra page height if view arrangement avoids the information box on the bottom right + if (((s1_x + s1_y + s2_x + s2_y) == 2) && (views[0]->width <= width/2)) + pageheight = pageh1; + else + pageheight = pageh2; + + //now evaluate available space / space required for each direction, and choose the smaller. + float working_scale = min((pagewidth - num_wide * min_space) / width, (pageheight - num_high * min_space) / height); + + //that gives the largest scale for which the min_space requirements can be met, but we want a 'sensible' scale, rather than 0.28457239! + //eg if working_scale = 0.115, then we want to use 0.1 + // if working_scale = 7.65, then we want to use 5 + // if working_scale = 76.5, then we want to use 50 + float exponent = floor(log10(working_scale)); //if working_scale = a * 10^b, what is b? + working_scale *= pow(10, -exponent); //now find what 'a' is. + + float valid_scales[2][8] = {{1, 1.25, 2, 2.5, 3.75, 5, 7.5, 10}, //equate to 1:10, 1:8, 1:5, 1:4, 3:8, 1:2, 3:4, 1:1 + {1, 1.5, 2, 3, 4, 5, 8, 10}}; //equate to 1:1, 3:2, 2:1, 3:1, 4:1, 5:1, 8:1, 10:1 + int i = 0; + while (valid_scales[(exponent>=0)][i] <= working_scale) //choose closest value smaller than 'a' from list. + i += 1; //choosing top list if exponent -ve, bottom list for +ve exponent + i -= 1; + float chosen_scale = valid_scales[(exponent>=0)][i]; + scale = chosen_scale * pow(10, exponent); //now have the appropriate scale, reapply the *10^b + + /////////////////////// + //now we move on to the placements + + width *= scale; + height *= scale; + + //which direction gives the smallest space between views? Space is given by (page size - size of views) / (number of spaces) + float space = min((pagewidth - width)/num_wide, (pageheight - height)/num_high); + + //now calculate the spacing of the secondary views from the primary one + //***********************spacing is currently view centre -> view centre******************************** + //so the spacing is equal to (primary centre -> prmry edge) + (secondary centre -> scdry edge) + space + //these depend upon whether secondary is vertically or horizontally primary from primary + + if (s1_x != 0) //secondary_1 is horizontally placed from primary + spacing_1 = space + scale*(views[0]->width + views[1]->width)/2; + else //secondary_1 is vertically placed from primary + spacing_1 = space + scale*(views[0]->height + views[1]->height)/2; + + + if (s2_x != 0) //same for secondary_2 + spacing_2 = space + scale*(views[0]->width + views[2]->width)/2; + else + spacing_2 = space + scale*(views[0]->height + views[2]->height)/2; + + spacing_1 = floor(spacing_1*10 + 0.5) / 10; + spacing_2 = floor(spacing_2*10 + 0.5) / 10; + + /////////////////////////////////////////// + //finally, evaluate position of primary view. + + int pos_wide = s1_x + s2_x; //=1 = primary on left, 0 = primary in middle, -1 = on right + int pos_high = s1_y + s2_y; //=1 = at top, 0 = in middle, -1 = at bottom + + if (pos_wide == 1) + x_pos = (pagewidth / 2.0 + margin) - ((width + space) - scale * views[0]->width)/2; + else if (pos_wide == 0) + x_pos = pagewidth / 2.0 + margin; + else + x_pos = (pagewidth / 2.0 + margin) + ((width + space) - scale * views[0]->width)/2; + + if (pos_high == 1) + y_pos = (pageheight / 2.0 + margin) - ((height + space) - scale * views[0]->height)/2; + else if (pos_high == 0) + y_pos = pageheight / 2.0 + margin; + else + y_pos = (pageheight / 2.0 + margin) + ((height + space) - scale * views[0]->height)/2; + + x_pos = floor(x_pos * 10 + 0.5) / 10; + y_pos = floor(y_pos * 10 + 0.5) / 10; + + //////////// + //update the gui boxes with calculated information + ui->scale->setText(QString::number(scale)); + ui->x->setText(QString::number(x_pos)); + ui->y->setText(QString::number(y_pos)); + ui->s1->setText(QString::number(spacing_1)); + ui->s2->setText(QString::number(spacing_2)); +} + +void TaskOrthoViews::compute() +{ +//secondary 1 + float s1_x = proj * transform[secondary_1][primary][0]; + float s1_y = proj * transform[secondary_1][primary][1]; + rotate_coords(s1_x,s1_y,rotate); + float s1_r = (rotate + transform[secondary_1][primary][2])%4; + +//secondary 2 + float s2_x = proj * transform[secondary_2][primary][0]; + float s2_y = proj * transform[secondary_2][primary][1]; + rotate_coords(s2_x,s2_y,rotate); + float s2_r = (rotate + transform[secondary_2][primary][2])%4; + + //autodims will retrieve information from views[] regarding image dimensions + //thus need to set views[] direction and orientation before calling autodims. + views[0]->setDir(primary); + views[0]->setOrientation(rotate); + + views[1]->setDir(secondary_1); + views[1]->setOrientation(s1_r); + + views[2]->setDir(secondary_2); + views[2]->setOrientation(s2_r); + + if (autoscale) + autodims(s1_x, s1_y, s2_x, s2_y); + + views[0]->setScale(scale); + views[0]->setPos(x_pos,y_pos); + + views[1]->setScale(scale); + views[1]->setPos(x_pos + spacing_1 * s1_x, y_pos + spacing_1 * s1_y); + + views[2]->setScale(scale); + views[2]->setPos(x_pos + spacing_2 * s2_x, y_pos + spacing_2 * s2_y); + + Command::updateActive(); + Command::commitCommand(); +} + +void TaskOrthoViews::projectionChanged(int index) +{ + proj = 2*(0.5-index); //gives -1 for 1st angle and 1 for 3rd + compute(); +} + +void TaskOrthoViews::setRotate(int r) +{ + rotate = r; + compute(); +} + +void TaskOrthoViews::populate_s1() +{ + ui->secondary_1->clear(); + ui->secondary_1->addItem(QString()); + + int i = 0; + int k = 0; + for (int j=1; j < 7; j++) + if (((j+1)/2 != (primary+1)/2) && (j != secondary_2)) + { + k += 1; + ui->secondary_1->addItem(QString::fromUtf8(number_to_name(j))); + if (j == secondary_1) + i = k; + } + + ui->secondary_1->setCurrentIndex(i); +} + +void TaskOrthoViews::populate_s2() +{ + ui->secondary_2->clear(); + ui->secondary_2->addItem(QString()); + + int i = 0; + int k = 0; + for (int j=1; j < 7; j++) + if (((j+1)/2 != (primary+1)/2) && (j != secondary_1)) + { + k += 1; + ui->secondary_2->addItem(QString::fromUtf8(number_to_name(j))); + if (j == secondary_2) + i = k; + } + + ui->secondary_2->setCurrentIndex(i); +} + +void TaskOrthoViews::setPrimary(int dir) +{ + if (dir == 0) + { + views[0]->activate(false); + views[1]->activate(false); + views[2]->activate(false); + primary = 0; + secondary_1 = 0; + secondary_2 = 0; + ui->secondary_1->setCurrentIndex(0); + ui->secondary_2->setCurrentIndex(0); + } + else + { + if (!views[0]->active) + views[0]->activate(true); + + primary = dir; + + if ((primary+1)/2 == (secondary_1+1)/2) //eg primary = 1, secondary_1 = 2 + { + views[1]->activate(false); + secondary_1 = 0; + ui->secondary_1->setCurrentIndex(0); + } + + if ((primary+1)/2 == (secondary_2+1)/2) + { + views[2]->activate(false); + secondary_2 = 0; + ui->secondary_2->setCurrentIndex(0); + } + populate_s1(); + populate_s2(); + compute(); + } +} + +void TaskOrthoViews::setSecondary_1(int dir) +{ + if (dir == 0) + { + views[1]->activate(false); + secondary_1 = 0; + } + else + { + QString text = ui->secondary_1->currentText(); + int value = name_to_number(text); + if (!views[1]->active) + views[1]->activate(true); + secondary_1 = value; + } + populate_s2(); + compute(); +} + +void TaskOrthoViews::setSecondary_2(int dir) +{ + if (dir == 0) + { + views[2]->activate(false); + secondary_2 = 0; + } + else + { + QString text = ui->secondary_2->currentText(); + int value = name_to_number(text); + if (!views[2]->active) + views[2]->activate(true); + secondary_2 = value; + } + populate_s1(); + compute(); +} + +void TaskOrthoViews::hidden(int i) +{ + views[0]->hidden(i); + views[1]->hidden(i); + views[2]->hidden(i); + Command::updateActive(); + Command::commitCommand(); +} + +void TaskOrthoViews::smooth(int i) +{ + views[0]->smooth(i); + views[1]->smooth(i); + views[2]->smooth(i); + Command::updateActive(); + Command::commitCommand(); +} + +void TaskOrthoViews::toggle_auto(int i) +{ + if (i == 2) //auto scale switched on + { + autoscale = true; + ui->scale->setEnabled(false); + ui->x->setEnabled(false); + ui->y->setEnabled(false); + ui->s1->setEnabled(false); + ui->s2->setEnabled(false); + ui->label_4->setEnabled(false); + ui->label_5->setEnabled(false); + ui->label_6->setEnabled(false); + compute(); + } + else + { + autoscale = false; + ui->scale->setEnabled(true); + ui->x->setEnabled(true); + ui->y->setEnabled(true); + ui->s1->setEnabled(true); + ui->s2->setEnabled(true); + ui->label_4->setEnabled(true); + ui->label_5->setEnabled(true); + ui->label_6->setEnabled(true); + } +} + +void TaskOrthoViews::data_entered() +{ + Command::doCommand(Command::Doc,"#Data entered"); + + bool ok; + + float value = ui->s1->text().toFloat(&ok); + if (ok) + spacing_1 = value; + else + { + ui->s1->setText(QString::number(spacing_1)); + return; + } + + value = ui->s2->text().toFloat(&ok); + if (ok) + spacing_2 = value; + else + { + ui->s2->setText(QString::number(spacing_2)); + return; + } + + value = ui->x->text().toFloat(&ok); + if (ok) + x_pos = value; + else + { + ui->x->setText(QString::number(x_pos)); + return; + } + + value = ui->y->text().toFloat(&ok); + if (ok) + y_pos = value; + else + { + ui->y->setText(QString::number(y_pos)); + return; + } + + value = ui->scale->text().toFloat(&ok); + if (ok) + scale = value; + else + { + ui->scale->setText(QString::number(scale)); + return; + } + compute(); +} + +bool TaskOrthoViews::user_input() +{ + //if user presses return, this is intercepted by FreeCAD which interprets it as activating the 'OK' button + //if return was pressed in a text box though, we don't want it to do 'OK', so check to see if a text box has been modified. + bool modified = (ui->s1->isModified() || ui->s2->isModified() || ui->x->isModified() || ui->y->isModified() || ui->scale->isModified()); + + if (modified) + { + ui->s1->setModified(false); + ui->s2->setModified(false); + ui->x->setModified(false); + ui->y->setModified(false); + ui->scale->setModified(false); + } + return modified; +} + +void TaskOrthoViews::clean_up(bool keep) +{ + if (keep) //user ok-ed the drawing + { + if (!views[0]->active) + views[0]->deleteme(); + if (!views[1]->active) + views[1]->deleteme(); + if (!views[2]->active) + views[2]->deleteme(); + } + else //user cancelled the drawing + { + views[0]->deleteme(); + views[1]->deleteme(); + views[2]->deleteme(); + } +} + + + + + + + + + + + + + + + + + + + + + +//************************************************************************** +//************************************************************************** +// TaskDialog +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TaskDlgOrthoViews::TaskDlgOrthoViews() + : TaskDialog() +{ + widget = new TaskOrthoViews(); + taskbox = new Gui::TaskView::TaskBox( + Gui::BitmapFactory().pixmap("actions/drawing-orthoviews"), widget->windowTitle(), true, 0); + taskbox->groupLayout()->addWidget(widget); + Content.push_back(taskbox); +} + +TaskDlgOrthoViews::~TaskDlgOrthoViews() +{ + +} + +//==== calls from the TaskView =============================================================== + + +void TaskDlgOrthoViews::open() +{ + +} + +void TaskDlgOrthoViews::clicked(int) +{ + +} + +bool TaskDlgOrthoViews::accept() +{ + bool check = widget->user_input(); + if (!check) + widget->clean_up(true); + + return !check; +} + +bool TaskDlgOrthoViews::reject() +{ + widget->clean_up(false); + return true; +} + + + + +#include "moc_TaskOrthoViews.cpp" diff --git a/src/Mod/Drawing/Gui/TaskOrthoViews.h b/src/Mod/Drawing/Gui/TaskOrthoViews.h new file mode 100644 index 000000000..57b2c95f2 --- /dev/null +++ b/src/Mod/Drawing/Gui/TaskOrthoViews.h @@ -0,0 +1,157 @@ +/*************************************************************************** + * Copyright (c) 2011 Joe Dowsett * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library 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 Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef GUI_TASKVIEW_TASKORTHOVIEWS_H +#define GUI_TASKVIEW_TASKORTHOVIEWS_H + +#include +#include +#include "ui_TaskOrthoViews.h" +#include + +class Ui_TaskOrthoViews; + +namespace DrawingGui { + + +class orthoView +{ +public: + orthoView(std::string, const char *, const char *, Base::BoundBox3d); + ~orthoView(); + + void activate(bool); + void setDir(int); + void setPos(float = 0, float = 0); + void setScale(float); + void setOrientation(int); + void deleteme(); + void hidden(int); + void smooth(int); + +public: + bool active; + float width; + float height; + +private: + void calcCentre(); + void updateView(); + +private: + std::string myname; + Base::BoundBox3d mybox; + int dir; + int angle; + int orientation; + float x, y; + float pageX, pageY; + float scale; +}; + + + + + + +class TaskOrthoViews : public QWidget//: public Gui::TaskView::TaskBox +{ + Q_OBJECT + +public: + TaskOrthoViews(QWidget *parent = 0); + ~TaskOrthoViews(); + bool user_input(); + void clean_up(bool); + +protected Q_SLOTS: + void setPrimary(int); + void setRotate(int); + void setSecondary_1(int); + void setSecondary_2(int); + void projectionChanged(int); + void hidden(int); + void smooth(int); + void toggle_auto(int); + void data_entered(); + +private: + void compute(); + void autodims(float, float, float, float); + void populate_s1(); + void populate_s2(); + +private: + class Private; + Ui_TaskOrthoViews * ui; + orthoView * views[3]; + int transform[7][7][3]; //matrix containing relative positions and rotations of secondary views depending upon primary view + int primary; //view direction of primary view + int secondary_1, secondary_2; //view direction of secondary views + int spacing_1, spacing_2; //spacings of secondary view centre from primary view centre + float x_pos, y_pos; //x and y coords for primary view + int rotate; //rotate primary view clockwise by rotate*90 + int proj; //first (=-1) or third (=1) angle projection + float scale; //scale of drawing + bool autoscale; //whether or not to run autodims + int pagewidth, pageh1, pageh2; //these are actually the available width and height, calculated in constructor. + int margin; + int min_space; //minimum space between views, and page edge +}; + + + + +////////////////////////////////////////////////////////////// + + + +/// simulation dialog for the TaskView +class TaskDlgOrthoViews : public Gui::TaskView::TaskDialog +{ + Q_OBJECT + +public: + TaskDlgOrthoViews(); + ~TaskDlgOrthoViews(); + + +public: + void open(); + bool accept(); + bool reject(); + void clicked(int); + +// QDialogButtonBox::StandardButtons getStandardButtons() const +// { return QDialogButtonBox::Ok|QDialogButtonBox::Cancel; } + +private: + TaskOrthoViews * widget; + Gui::TaskView::TaskBox* taskbox; + +}; + +} //namespace DrawingGui + + +#endif // GUI_TASKVIEW_OrthoViews_H + diff --git a/src/Mod/Drawing/Gui/TaskOrthoViews.ui b/src/Mod/Drawing/Gui/TaskOrthoViews.ui new file mode 100644 index 000000000..aae0b27e6 --- /dev/null +++ b/src/Mod/Drawing/Gui/TaskOrthoViews.ui @@ -0,0 +1,379 @@ + + + DrawingGui::TaskOrthoViews + + + + 0 + 0 + 272 + 394 + + + + + 0 + 0 + + + + Orthographic Projection + + + + + + + + Projection + + + + + + + false + + + + Third Angle + + + + + First Angle + + + + + + + + + + + + + + Primary View + + + + + + + - Rotate + + + Qt::AlignCenter + + + + + + + + + + + QComboBox::AdjustToContentsOnFirstShow + + + true + + + + + + + + + Front + + + + + Back + + + + + Right + + + + + Left + + + + + Top + + + + + Bottom + + + + + + + + + 0 + + + + + 90 + + + + + 180 + + + + + 270 + + + + + + + + + + + + Qt::Horizontal + + + + + + + + + + + Secondary views + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + + + + + + true + + + Auto scale / position + + + true + + + + + + + + + + + false + + + Scale + + + + + + + false + + + Primary x / y + + + + + + + false + + + Secondary spacings + + + + + + + + + + + false + + + + 0 + 0 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + false + + + + 0 + 0 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + false + + + + 0 + 0 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + false + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + false + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + + Qt::Horizontal + + + + + + + true + + + Show hidden + + + + + + + Show smooth + + + + + + + + diff --git a/src/Mod/Drawing/Gui/Workbench.cpp b/src/Mod/Drawing/Gui/Workbench.cpp index badf31473..993a77462 100644 --- a/src/Mod/Drawing/Gui/Workbench.cpp +++ b/src/Mod/Drawing/Gui/Workbench.cpp @@ -60,6 +60,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const //*part << "Drawing_NewA3Landscape"; *part << "Drawing_NewPage"; *part << "Drawing_NewView"; + *part << "Drawing_OrthoViews"; *part << "Drawing_ExportPage"; return root; @@ -74,6 +75,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const //*part << "Drawing_NewA3Landscape"; *part << "Drawing_NewPage"; *part << "Drawing_NewView"; + *part << "Drawing_OrthoViews"; *part << "Drawing_ExportPage"; return root; } @@ -89,6 +91,7 @@ Gui::ToolBarItem* Workbench::setupCommandBars() const img->setCommand("Drawing types"); //*img << "Drawing_NewA3Landscape"; *img << "Drawing_NewPage"; + *img << "Drawing_OrthoViews"; img = new Gui::ToolBarItem(root); img->setCommand("Views"); *img << "Drawing_NewView";