src/blockwidget.h \
src/commandprocessor.h \
src/consolewidget.h \
+ src/drawingsettingsdlg.h \
src/drawingview.h \
src/fileio.h \
src/generaltab.h \
src/rect.h \
src/settingsdialog.h \
src/structs.h \
+ src/units.h \
src/utils.h \
src/vector.h
src/blockwidget.cpp \
src/commandprocessor.cpp \
src/consolewidget.cpp \
+ src/drawingsettingsdlg.cpp \
src/drawingview.cpp \
src/fileio.cpp \
src/generaltab.cpp \
src/promptlineedit.cpp \
src/rect.cpp \
src/settingsdialog.cpp \
+ src/units.cpp \
src/utils.cpp \
src/vector.cpp
#include "blockwidget.h"
#include "commandprocessor.h"
#include "consolewidget.h"
+#include "drawingsettingsdlg.h"
#include "drawingview.h"
#include "fileio.h"
#include "generaltab.h"
else
Global::tool = TTNone;
- cw->SetToolPrompt();//cw->cmdline);
+ cw->SetToolPrompt();
drawing->update();
}
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.
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()));
menu->addAction(addSplineAct);
menu->addAction(addDimensionAct);
menu->addSeparator();
+ menu->addAction(drawingSettingsAct);
menu->addAction(settingsAct);
menu = menuBar()->addMenu(tr("&Help"));
void ZoomOutTool(void);
void HelpAbout(void);
void Settings(void);
+ void DrawingSettings(void);
void HandleGrouping(void);
void HandleConnection(void);
void HandleDisconnection(void);
QAction * fileCloseAct;
QAction * exitAct;
QAction * settingsAct;
+ QAction * drawingSettingsAct;
QAction * fixAngleAct;
QAction * fixLengthAct;
QAction * deleteAct;
--- /dev/null
+//
+// 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 <jlhamm@acm.org>
+//
+// 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()
+{
+}
--- /dev/null
+#ifndef __DRAWINGSETTINGSDLG_H__
+#define __DRAWINGSETTINGSDLG_H__
+
+#include <QtWidgets>
+
+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__
#include "painter.h"
#include "penwidget.h"
#include "structs.h"
+#include "units.h"
#include "utils.h"
#define BACKGROUND_MAX_SIZE 512
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 };
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().
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;
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;
- 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
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; i<Global::numLayers; i++)
else if (version == 1.2f)
return LoadVersion1_2(file, drawing);
-//printf("LoadAtnsFile: Could not locate version! (version=%f)\n", version);
return false;
}
/*static*/ bool FileIO::LoadVersion1_2(FILE * file, Container * drawing)
{
- int hidden, locked;
+ int hidden, locked, props = 0;
char textBuffer[65536];
- // Load layer information first
+ // Load drawing properties, if any, first
+ fscanf(file, "PROPERTIES %i\n", &props);
+
+ if (props == 4)
+ {
+ fscanf(file, "BASE_UNIT %i\n", &(drawing->baseUnit));
+ 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; i<Global::numLayers; i++)
case OTPolygon:
break;
case OTDimension:
-// fprintf(file, "DIMENSION %i (%lf,%lf) (%lf,%lf) %i\n", layer, position.x, position.y, endpoint.x, endpoint.y, dimensionType);
fprintf(file, "DIMENSION %i (%lf,%lf) (%lf,%lf) %i %lf", obj->layer, 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:
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) {}
--- /dev/null
+//
+// 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 <jlhamm@acm.org>
+//
+// 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();
+}
--- /dev/null
+#ifndef __UNITS_H__
+#define __UNITS_H__
+
+#include <QString>
+#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__