From: Shamus Hammons Date: Thu, 6 Jan 2022 18:50:39 +0000 (-0600) Subject: Added base units & display style to drawing. X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=architektonas;a=commitdiff_plain;h=41644f6a841b45cb6f1f7a96c93fd550f67a7974 Added base units & display style to drawing. This also gets saved with the drawing; the ATNS file format stays at v1.2 as these will be set to defaults if they are missing. Also, there is now a dialog to change these setting per drawing; currently any change of base unit to a current drawing does no unit conversion to the drawing itself. This will be rectified in a future revision. --- diff --git a/architektonas.pro b/architektonas.pro index 86dd646..5f68a70 100644 --- a/architektonas.pro +++ b/architektonas.pro @@ -54,6 +54,7 @@ HEADERS = \ src/blockwidget.h \ src/commandprocessor.h \ src/consolewidget.h \ + src/drawingsettingsdlg.h \ src/drawingview.h \ src/fileio.h \ src/generaltab.h \ @@ -70,6 +71,7 @@ HEADERS = \ src/rect.h \ src/settingsdialog.h \ src/structs.h \ + src/units.h \ src/utils.h \ src/vector.h @@ -81,6 +83,7 @@ SOURCES = \ src/blockwidget.cpp \ src/commandprocessor.cpp \ src/consolewidget.cpp \ + src/drawingsettingsdlg.cpp \ src/drawingview.cpp \ src/fileio.cpp \ src/generaltab.cpp \ @@ -95,6 +98,7 @@ SOURCES = \ src/promptlineedit.cpp \ src/rect.cpp \ src/settingsdialog.cpp \ + src/units.cpp \ src/utils.cpp \ src/vector.cpp diff --git a/src/applicationwindow.cpp b/src/applicationwindow.cpp index 8c114c8..8bbdbc1 100644 --- a/src/applicationwindow.cpp +++ b/src/applicationwindow.cpp @@ -33,6 +33,7 @@ #include "blockwidget.h" #include "commandprocessor.h" #include "consolewidget.h" +#include "drawingsettingsdlg.h" #include "drawingview.h" #include "fileio.h" #include "generaltab.h" @@ -596,7 +597,7 @@ void ApplicationWindow::SetInternalToolStates(void) else Global::tool = TTNone; - cw->SetToolPrompt();//cw->cmdline); + cw->SetToolPrompt(); drawing->update(); } @@ -618,6 +619,25 @@ void ApplicationWindow::Settings(void) WriteSettings(); } +void ApplicationWindow::DrawingSettings(void) +{ + DrawingSettingsDlg dlg(this); + dlg.baseUnit->setCurrentIndex(drawing->document.baseUnit); + dlg.unitStyle->setCurrentIndex(drawing->document.unitStyle); + dlg.decimalPrecision->setCurrentIndex(drawing->document.decimalPrecision); + dlg.fractionalPrecision->setCurrentIndex(drawing->document.fractionalPrecision); + + if (dlg.exec() == false) + return; + + // Deal with stuff here (since user hit "OK" button...) + drawing->document.baseUnit = dlg.baseUnit->currentIndex(); + drawing->document.unitStyle = dlg.unitStyle->currentIndex(); + drawing->document.decimalPrecision= dlg.decimalPrecision->currentIndex(); + drawing->document.fractionalPrecision = dlg.fractionalPrecision->currentIndex(); + drawing->update(); +} + // // Group a bunch of selected objects (which can include other groups) together // or ungroup a selected group. @@ -904,6 +924,9 @@ void ApplicationWindow::CreateActions(void) settingsAct = CreateAction(tr("&Settings"), tr("Settings"), tr("Change certain defaults for Architektonas."), QIcon(":/res/settings.png"), QKeySequence()); connect(settingsAct, SIGNAL(triggered()), this, SLOT(Settings())); + drawingSettingsAct = CreateAction(tr("&Drawing Settings"), tr("Drawing settings"), tr("Change certain defaults for the current drawing."), QIcon(":/res/settings.png"), QKeySequence()); + connect(drawingSettingsAct, SIGNAL(triggered()), this, SLOT(DrawingSettings())); + groupAct = CreateAction(tr("&Group"), tr("Group"), tr("Group/ungroup selected objects."), QIcon(":/res/group-tool.png"), QKeySequence("g")); connect(groupAct, SIGNAL(triggered()), this, SLOT(HandleGrouping())); @@ -1044,6 +1067,7 @@ void ApplicationWindow::CreateMenus(void) menu->addAction(addSplineAct); menu->addAction(addDimensionAct); menu->addSeparator(); + menu->addAction(drawingSettingsAct); menu->addAction(settingsAct); menu = menuBar()->addMenu(tr("&Help")); diff --git a/src/applicationwindow.h b/src/applicationwindow.h index be245b0..8b99218 100644 --- a/src/applicationwindow.h +++ b/src/applicationwindow.h @@ -54,6 +54,7 @@ class ApplicationWindow: public QMainWindow void ZoomOutTool(void); void HelpAbout(void); void Settings(void); + void DrawingSettings(void); void HandleGrouping(void); void HandleConnection(void); void HandleDisconnection(void); @@ -103,6 +104,7 @@ class ApplicationWindow: public QMainWindow QAction * fileCloseAct; QAction * exitAct; QAction * settingsAct; + QAction * drawingSettingsAct; QAction * fixAngleAct; QAction * fixLengthAct; QAction * deleteAct; diff --git a/src/drawingsettingsdlg.cpp b/src/drawingsettingsdlg.cpp new file mode 100644 index 0000000..ede8cb9 --- /dev/null +++ b/src/drawingsettingsdlg.cpp @@ -0,0 +1,50 @@ +// +// drawingsettingsdlg.cpp: Dialog for changing a drawing's settings +// +// Part of the Architektonas Project +// (C) 2021 Underground Software +// See the README and GPLv3 files for licensing and warranty information +// +// JLH = James Hammons +// +// WHO WHEN WHAT +// --- ---------- ------------------------------------------------------------ +// JLH 12/31/2021 Created this file + +#include "drawingsettingsdlg.h" + +DrawingSettingsDlg::DrawingSettingsDlg(QWidget * parent/*= 0*/): QDialog(parent), baseUnit(new QComboBox(this)), unitStyle(new QComboBox(this)), decimalPrecision(new QComboBox(this)), fractionalPrecision(new QComboBox(this)) +{ + QStringList buList = { "Inch", "Foot", "Yard", "Mile", "mm", "cm", "m", "km" }; + QStringList usList = { "Decimal", "Fractional" }; + QStringList dpList = { "0.1", "0.01", "0.001", "0.0001", "0.00001", "0.000001" }; + QStringList fpList = { "1/2", "1/4", "1/8", "1/16", "1/32", "1/64" }; + + baseUnit->insertItems(0, buList); + unitStyle->insertItems(0, usList); + decimalPrecision->insertItems(0, dpList); + fractionalPrecision->insertItems(0, fpList); + + QFormLayout * fl = new QFormLayout; + + fl->addRow(tr("Base Unit:"), baseUnit); + fl->addRow(tr("Unit Style:"), unitStyle); + fl->addRow(tr("Decimal Precision:"), decimalPrecision); + fl->addRow(tr("Fractional Precision:"), fractionalPrecision); + + buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + + connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); + connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + + QVBoxLayout * mainLayout = new QVBoxLayout; + mainLayout->addLayout(fl); + mainLayout->addWidget(buttonBox); + setLayout(mainLayout); + + setWindowTitle(tr("Drawing Settings")); +} + +DrawingSettingsDlg::~DrawingSettingsDlg() +{ +} diff --git a/src/drawingsettingsdlg.h b/src/drawingsettingsdlg.h new file mode 100644 index 0000000..19c9d98 --- /dev/null +++ b/src/drawingsettingsdlg.h @@ -0,0 +1,24 @@ +#ifndef __DRAWINGSETTINGSDLG_H__ +#define __DRAWINGSETTINGSDLG_H__ + +#include + +class DrawingSettingsDlg: public QDialog +{ + Q_OBJECT + + public: + DrawingSettingsDlg(QWidget * parent = 0); + ~DrawingSettingsDlg(); + + private: + QDialogButtonBox * buttonBox; + + public: + QComboBox * baseUnit; + QComboBox * unitStyle; + QComboBox * decimalPrecision; + QComboBox * fractionalPrecision; +}; + +#endif // __DRAWINGSETTINGSDLG_H__ diff --git a/src/drawingview.cpp b/src/drawingview.cpp index 3baa2d7..3b6f92c 100644 --- a/src/drawingview.cpp +++ b/src/drawingview.cpp @@ -41,6 +41,7 @@ #include "painter.h" #include "penwidget.h" #include "structs.h" +#include "units.h" #include "utils.h" #define BACKGROUND_MAX_SIZE 512 @@ -52,8 +53,9 @@ DrawingView::DrawingView(QWidget * parent/*= NULL*/): QWidget(parent), gridBackground(BACKGROUND_MAX_SIZE, BACKGROUND_MAX_SIZE), scale(1.0), offsetX(-10), offsetY(-10), supressSelected(false), document(true), - gridPixels(0), collided(false), scrollDrag(false), hoverPointValid(false), - hoveringIntersection(false), dragged(NULL), draggingObject(false), + gridPixels(0), collided(false), scrollDrag(false), + hoverPointValid(false), hoveringIntersection(false), + dragged(NULL), draggingObject(false), angleSnap(false), dirty(false) { //wtf? doesn't work except in c++11??? document = { 0 }; @@ -556,20 +558,7 @@ void DrawingView::RenderObjects(Painter * painter, VPVector & v, int layer, bool painter->SetFont(QFont("Arial", 8.0 * Global::zoom * scaledThickness)); Point ctr = p2 + (Vector(p2, p1) / 2.0); - QString dimText; - - if (length < 12.0) - dimText = QString("%1\"").arg(length); - else - { - double feet = (double)((int)length / 12); - double inches = length - (feet * 12.0); - - if (inches == 0) - dimText = QString("%1'").arg(feet); - else - dimText = QString("%1' %2\"").arg(feet).arg(inches); - } + QString dimText = GetDimensionText(&document, length); /* Where is the text offset? It looks like it's drawing in the center, but obviously it isn't. It isn't here, it's in Painter::DrawAngledText(). @@ -3034,7 +3023,7 @@ N.B.: Mixing fixed length with fixed angle (and in this order) is probably *not* obj->radius[0] = Vector::Magnitude(obj->p[0], point); QString text = QObject::tr("Radius: %1\nScale: %2%"); - informativeText = text.arg(obj->radius[0], 0, 'd', 4).arg(obj->radius[0] / oldRadius * 100.0, 0, 'd', 0); + informativeText = text.arg(obj->radius[0], 0, 'f', 4).arg(obj->radius[0] / oldRadius * 100.0, 0, 'f', 0); } break; diff --git a/src/drawingview.h b/src/drawingview.h index 5906766..0d48392 100644 --- a/src/drawingview.h +++ b/src/drawingview.h @@ -85,16 +85,16 @@ class DrawingView: public QWidget private: QPixmap gridBackground; - double scale; // Window scaling factor - int32_t offsetX, offsetY; // Window offsets + double scale; // Window scaling factor + int32_t offsetX, offsetY; // Window offsets bool supressSelected; QCursor curMarker; QCursor curDropper; uint32_t currentSelect; public: Container document; - uint32_t gridPixels; // Grid size in pixels - double gridPixelsF; // Grid size in pixels (float) + uint32_t gridPixels; // Grid size in pixels + double gridPixelsF; // Grid size in pixels (float) bool collided; bool scrollDrag; Vector oldPoint; diff --git a/src/fileio.cpp b/src/fileio.cpp index 1b11902..3ce4470 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -108,11 +108,8 @@ OTHER CONSIDERATIONS: - Need to figure out how to store the Layer list (should layer list be optional?) - Need to figure out how to store the Block list and blocks - */ -//enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFLine, OTFCircle, OTFArc, -// OTFDimension, OTFPolygon, OTFText, OTFImage, OTFBlock, OTFEndOfFile }; enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFObject, OTFEndOfFile }; // Instantiate class variables @@ -127,6 +124,12 @@ enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFObject, OTFEndOfFile }; Container, otherwise it enumerates all objects within itself. */ fprintf(file, "ARCHITEKTONAS DRAWING V1.2\n"); + fprintf(file, "PROPERTIES 4\n"); + fprintf(file, "BASE_UNIT %i\n", c->baseUnit); + fprintf(file, "UNIT_STYLE %i\n", c->unitStyle); + fprintf(file, "DEC_PREC %i\n", c->decimalPrecision); + fprintf(file, "FRAC_PREC %i\n", c->fractionalPrecision); + fprintf(file, "LAYERS %i\n", Global::numLayers); for(int i=0; ibaseUnit)); + fscanf(file, "UNIT_STYLE %i\n", &(drawing->unitStyle)); + fscanf(file, "DEC_PREC %i\n", &(drawing->decimalPrecision)); + fscanf(file, "FRAC_PREC %i\n", &(drawing->fractionalPrecision)); + } + + // Load layer information next fscanf(file, "LAYERS %i\n", &Global::numLayers); for(int i=0; ilayer, obj->p[0].x, obj->p[0].y, obj->p[1].x, obj->p[1].y, ((Dimension *)obj)->subtype, ((Dimension *)obj)->offset); break; case OTSpline: diff --git a/src/structs.h b/src/structs.h index d0dbb55..47d8d85 100644 --- a/src/structs.h +++ b/src/structs.h @@ -156,7 +156,12 @@ struct Container { bool topLevel; Object * clicked; - Container(bool tl = false): type(OTContainer), id(Global::objectID++), selected(false), hovered(false), hitObject(false), topLevel(tl), clicked(NULL) {} + int baseUnit; // Type of BasicUnit as seen above + int unitStyle; // 0 = decimal, 1 = fractional + int decimalPrecision; // 0-5, which, +1, is # of decimal places + int fractionalPrecision; // 0-5, which, +1, is 1/(2^n) + + Container(bool tl = false): type(OTContainer), id(Global::objectID++), selected(false), hovered(false), hitObject(false), topLevel(tl), clicked(NULL), baseUnit(0), unitStyle(0), decimalPrecision(3), fractionalPrecision(4) {} void Add(void * obj) { objects.push_back(obj); } void Add(VPVector objs) { objects.insert(objects.end(), objs.begin(), objs.end()); } // void DeleteContents(void) {} diff --git a/src/units.cpp b/src/units.cpp new file mode 100644 index 0000000..7b203a1 --- /dev/null +++ b/src/units.cpp @@ -0,0 +1,130 @@ +// +// units.cpp: Unit conversion/description +// +// Part of the Architektonas Project +// (C) 2022 Underground Software +// See the README and GPLv3 files for licensing and warranty information +// +// JLH = James Hammons +// +// WHO WHEN WHAT +// --- ---------- ------------------------------------------------------------ +// JLH 01/04/2022 Created this file + +#include "units.h" + +QString GetDimensionText(Container * c, double length) +{ + QString dimText; + + if (c->unitStyle == 0) + { + // Decimal style + int decPrecision = c->decimalPrecision + 1; + + if (c->baseUnit == BUInch) + { + dimText = QString("%1\"").arg(length, 0, 'f', decPrecision); + } + else if (c->baseUnit == BUFoot) + { + double feet = (double)((int)length); + double inches = (length - feet) * 12.0; + + QString ftText = (feet != 0 ? QString("%1'").arg(feet) : ""); + QString inText = (inches != 0 ? QString(" %1\"").arg(inches, 0, 'f', decPrecision) : ""); + + dimText = QString("%1%2").arg(ftText).arg(inText).trimmed(); + } + else if (c->baseUnit == BUYard) + { + double yards = (double)((int)length); + double feet = (length - yards) * 3.0; + double inches = (feet - ((int)feet)) * 12.0; + feet = (double)((int)feet); // Integerize the feet now... + + QString ydText = (yards != 0 ? QString("%1 yd").arg(yards) : ""); + QString ftText = (feet != 0 ? QString(" %1'").arg(feet) : ""); + QString inText = (inches != 0 ? QString(" %1\"").arg(inches, 0, 'f', decPrecision) : ""); + + dimText = QString("%1%2%3") + .arg(ydText) + .arg(ftText) + .arg(inText) + .trimmed(); + } + else // mile, mm, cm, m, km + { + dimText = QString("%1 %2") + .arg(length, 0, 'f', decPrecision) + .arg(buShortName[c->baseUnit]); + } + } + else + { + // Fractional style + int fracPrecision = 1 << (c->fractionalPrecision + 1); + + if (c->baseUnit == BUInch) + { + dimText = MakeFraction(length, fracPrecision) + QChar('"'); + } + else if (c->baseUnit == BUFoot) + { + double feet = (double)((int)length); + double inches = (length - feet) * 12.0; + + QString ftText = (feet != 0 ? QString("%1'").arg(feet) : ""); + QString inText = (inches != 0 ? MakeFraction(inches, fracPrecision) + QChar('"') : ""); + + dimText = QString("%1 %2").arg(ftText).arg(inText).trimmed(); + } + else + { + dimText = QString("%1 %2").arg(MakeFraction(length, fracPrecision)).arg(buShortName[c->baseUnit]); + } + } + + return dimText; +} + +// +// Create a string that represents the passed in double as a proper fraction +// with the given precision. Fractions are rounded to the given precision +// (which represents the denominator of the fraction). +// +QString MakeFraction(double num, int precision) +{ + int intPart = (int)num; + double fraction = num - (double)intPart; + int numerator = (int)(((double)precision * fraction) + 0.5); + + // There's a chance we rounded up to the next whole number; if so, we fix + // that here. + if (numerator == precision) + { + intPart++; + numerator = 0; + } + + // Reduce the fraction by casting out factors of two (we assume the + // precision will always be a power of two); that is, if there is a + // denominator to reduce. + if (numerator > 0) + { + // Divide fraction by two while the denominator is not odd. N.B.: This + // will always end, as any non-zero number will eventually have a 1-bit + // in it somewhere, which we shift down to the low bit position with + // each iteration. + while ((numerator & 0x01) == 0) + { + numerator /= 2; + precision /= 2; + } + } + + QString intText = (intPart != 0 ? QString("%1").arg(intPart) : ""); + QString fracText = (numerator != 0 ? QString(" %1/%2").arg(numerator).arg(precision) : ""); + + return QString("%1%2").arg(intText).arg(fracText).trimmed(); +} diff --git a/src/units.h b/src/units.h new file mode 100644 index 0000000..e372aff --- /dev/null +++ b/src/units.h @@ -0,0 +1,13 @@ +#ifndef __UNITS_H__ +#define __UNITS_H__ + +#include +#include "structs.h" + +#define INCHES_TO_MM 25.4 +#define MM_TO_INCHES (1.0 / 25.4) + +QString GetDimensionText(Container *, double); +QString MakeFraction(double, int); + +#endif // __UNITS_H__