├── LICENSE.txt
├── README.md
├── contributing.md
└── pdCalc
├── LICENSE.GPL3.txt
├── common.pri
├── pdCalc.pro
├── src
├── app
│ ├── app.pro
│ ├── pdCalc-simple-cli
│ │ ├── main.cpp
│ │ └── pdCalc-simple-cli.pro
│ ├── pdCalc-simple-gui
│ │ ├── main.cpp
│ │ └── pdCalc-simple-gui.pro
│ └── pdCalc
│ │ ├── main.cpp
│ │ └── pdCalc.pro
├── backend
│ ├── AppObservers.cpp
│ ├── AppObservers.h
│ ├── Command.cpp
│ ├── Command.h
│ ├── CommandDispatcher.cpp
│ ├── CommandDispatcher.h
│ ├── CommandManager.cpp
│ ├── CommandManager.h
│ ├── CommandRepository.cpp
│ ├── CommandRepository.h
│ ├── CoreCommands.cpp
│ ├── CoreCommands.h
│ ├── DynamicLoader.cpp
│ ├── DynamicLoader.h
│ ├── PlatformFactory.cpp
│ ├── PlatformFactory.h
│ ├── Plugin.h
│ ├── PluginLoader.cpp
│ ├── PluginLoader.h
│ ├── PosixDynamicLoader.cpp
│ ├── PosixDynamicLoader.h
│ ├── PosixFactory.cpp
│ ├── PosixFactory.h
│ ├── Stack.cpp
│ ├── Stack.h
│ ├── StackPluginInterface.cpp
│ ├── StackPluginInterface.h
│ ├── StoredProcedure.cpp
│ ├── StoredProcedure.h
│ ├── WindowsDynamicLoader.cpp
│ ├── WindowsDynamicLoader.h
│ ├── WindowsFactory.cpp
│ ├── WindowsFactory.h
│ └── backend.pro
├── plugins
│ ├── hyperbolicLnPlugin
│ │ ├── HyperbolicLnPlugin.cpp
│ │ ├── HyperbolicLnPlugin.h
│ │ └── hyperbolicLnPlugin.pro
│ ├── plugins.pdp.unix
│ ├── plugins.pdp.win
│ └── plugins.pro
├── src.pro
├── ui
│ ├── cli
│ │ ├── Cli.cpp
│ │ ├── Cli.h
│ │ └── cli.pro
│ └── gui
│ │ ├── CommandButton.cpp
│ │ ├── CommandButton.h
│ │ ├── Display.cpp
│ │ ├── Display.h
│ │ ├── GuiModel.cpp
│ │ ├── GuiModel.h
│ │ ├── InputWidget.cpp
│ │ ├── InputWidget.h
│ │ ├── LookAndFeel.cpp
│ │ ├── LookAndFeel.h
│ │ ├── MainWindow.cpp
│ │ ├── MainWindow.h
│ │ ├── StoredProcedureDialog.cpp
│ │ ├── StoredProcedureDialog.h
│ │ └── gui.pro
└── utilities
│ ├── Exception.h
│ ├── Observer.cpp
│ ├── Observer.h
│ ├── Publisher.cpp
│ ├── Publisher.h
│ ├── Tokenizer.cpp
│ ├── Tokenizer.h
│ ├── UserInterface.cpp
│ ├── UserInterface.h
│ └── utilities.pro
└── test
├── backendTest
├── CommandDispatcherTest.cpp
├── CommandDispatcherTest.h
├── CommandManagerTest.cpp
├── CommandManagerTest.h
├── CommandRepositoryTest.cpp
├── CommandRepositoryTest.h
├── CoreCommandsTest.cpp
├── CoreCommandsTest.h
├── PluginLoaderTest.cpp
├── PluginLoaderTest.h
├── StackTest.cpp
├── StackTest.h
├── StoredProcedureTest.cpp
├── StoredProcedureTest.h
├── backendTest.pro
├── hypotenuse
├── plugins.unix.pdp
└── plugins.win.pdp
├── cliTest
├── CliTest.cpp
├── CliTest.h
├── cliTest.pro
└── testCases
│ ├── baselineCli1.txt
│ ├── baselineCli2.txt
│ ├── inputCli1.txt
│ └── inputCli2.txt
├── guiTest
├── DisplayTest.cpp
├── DisplayTest.h
└── guiTest.pro
├── pluginsTest
├── HyperbolicLnPluginTest.cpp
├── HyperbolicLnPluginTest.h
└── pluginsTest.pro
├── test.pro
├── testDriver
├── main.cpp
└── testDriver.pro
└── utilitiesTest
├── PublisherObserverTest.cpp
├── PublisherObserverTest.h
├── TokenizerTest.cpp
├── TokenizerTest.h
└── utilitiesTest.pro
/LICENSE.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/practical-cplusplus-design/96f77bb618e6569574441a679bbcc1dacf3fd438/LICENSE.txt
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Apress Source Code
2 |
3 | This repository accompanies [*Practical C++ Design*](http://www.apress.com/9781484230565) by Adam B. Singer (Apress, 2017).
4 |
5 | [comment]: #cover
6 |
7 |
8 | Download the files as a zip using the green button, or clone the repository to your machine using Git.
9 |
10 | ## Releases
11 |
12 | Release v1.0 corresponds to the code in the published book, without corrections or updates.
13 |
14 | ## Contributions
15 |
16 | See the file Contributing.md for more information on how you can contribute to this repository.
17 |
--------------------------------------------------------------------------------
/contributing.md:
--------------------------------------------------------------------------------
1 | # Contributing to Apress Source Code
2 |
3 | Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers.
4 |
5 | ## How to Contribute
6 |
7 | 1. Make sure you have a GitHub account.
8 | 2. Fork the repository for the relevant book.
9 | 3. Create a new branch on which to make your change, e.g.
10 | `git checkout -b my_code_contribution`
11 | 4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted.
12 | 5. Submit a pull request.
13 |
14 | Thank you for your contribution!
--------------------------------------------------------------------------------
/pdCalc/common.pri:
--------------------------------------------------------------------------------
1 | CONFIG(debug, debug|release): DEFINES += DEBUG
2 | CONFIG(release, debug|release): DEFINES += RELEASE
3 | VERSION = 1.0.0
4 | VERSION_STR = '\\"$${VERSION}\\"'
5 | DEFINES += PDCALC_VERSION=\"$${VERSION_STR}\"
6 | CONFIG += c++14
7 |
8 | unix:DEFINES += POSIX
9 | win32:DEFINES += WIN32
10 |
11 | # to avoid declspec nonsense
12 | win32:QMAKE_LFLAGS += -Wl,--no-undefined --enable-runtime-pseudo-reloc
13 |
--------------------------------------------------------------------------------
/pdCalc/pdCalc.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = subdirs
2 |
3 | SUBDIRS += src \
4 | test
5 |
6 |
--------------------------------------------------------------------------------
/pdCalc/src/app/app.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = subdirs
2 |
3 | SUBDIRS += pdCalc \
4 | pdCalc-simple-cli \
5 | pdCalc-simple-gui
6 |
--------------------------------------------------------------------------------
/pdCalc/src/app/pdCalc-simple-cli/main.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include
20 | #include
21 | #include "ui/cli/Cli.h"
22 | #include "backend/CommandDispatcher.h"
23 | #include "backend/AppObservers.h"
24 | #include "backend/Stack.h"
25 | #include "backend/CoreCommands.h"
26 |
27 | // I usually don't make blanket using namespace statements, but this
28 | // example is meant to be simple.
29 | using namespace pdCalc;
30 |
31 | using std::cout;
32 | using std::endl;
33 | using std::make_unique;
34 |
35 | int main()
36 | {
37 | Cli cli{std::cin, std::cout};
38 |
39 | CommandDispatcher ce{cli};
40 |
41 | RegisterCoreCommands(cli);
42 |
43 | cli.attach(UserInterface::CommandEntered, make_unique(ce) );
44 |
45 | Stack::Instance().attach(Stack::StackChanged, make_unique(cli) );
46 |
47 | cli.execute();
48 |
49 | return 0;
50 | }
51 |
--------------------------------------------------------------------------------
/pdCalc/src/app/pdCalc-simple-cli/pdCalc-simple-cli.pro:
--------------------------------------------------------------------------------
1 | HOME = ../../..
2 | include ($$HOME/common.pri)
3 | TEMPLATE = app
4 | TARGET = pdCalc-simple-cli
5 | DEPENDPATH += .
6 | INCLUDEPATH += $$HOME/src
7 | DESTDIR = $$HOME/bin
8 |
9 | win32:CONFIG += console
10 |
11 | SOURCES += main.cpp
12 |
13 | unix:LIBS += -L$$HOME/lib -lpdCalcCli -lpdCalcBackend -lpdCalcUtilities
14 | win32:LIBS += -L$$HOME/bin -lpdCalcCli1 -lpdCalcBackend1 -lpdCalcUtilities1
15 |
--------------------------------------------------------------------------------
/pdCalc/src/app/pdCalc-simple-gui/main.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include
20 | #include
21 | #include "backend/CommandDispatcher.h"
22 | #include "backend/AppObservers.h"
23 | #include "backend/Stack.h"
24 | #include "backend/CoreCommands.h"
25 | #include "ui/gui/MainWindow.h"
26 | #include
27 |
28 | // I usually don't make blanket using namespace statements, but this
29 | // example is meant to be simple.
30 | using namespace pdCalc;
31 |
32 | using std::cout;
33 | using std::endl;
34 | using std::make_unique;
35 |
36 | int main(int argc, char* argv[])
37 | {
38 | QApplication app{argc, argv};
39 | MainWindow gui{argc, argv};
40 |
41 | CommandDispatcher ce{gui};
42 |
43 | RegisterCoreCommands(gui);
44 |
45 | gui.attach(UserInterface::CommandEntered, make_unique(ce) );
46 |
47 | Stack::Instance().attach(Stack::StackChanged, make_unique( gui ) );
48 |
49 | gui.setupFinalButtons();
50 | gui.show();
51 | gui.fixSize();
52 |
53 | return app.exec();
54 | }
55 |
--------------------------------------------------------------------------------
/pdCalc/src/app/pdCalc-simple-gui/pdCalc-simple-gui.pro:
--------------------------------------------------------------------------------
1 | HOME = ../../..
2 | include ($$HOME/common.pri)
3 | TEMPLATE = app
4 | TARGET = pdCalc-simple-gui
5 | DEPENDPATH += .
6 | INCLUDEPATH += $$HOME/src
7 | DESTDIR = $$HOME/bin
8 |
9 | QT += widgets
10 |
11 | SOURCES += main.cpp
12 |
13 | unix:LIBS += -L$$HOME/lib -lpdCalcGui -lpdCalcBackend -lpdCalcUtilities
14 | win32:LIBS += -L$$HOME/bin -lpdCalcGui1 -lpdCalcBackend1 -lpdCalcUtilities1
15 |
--------------------------------------------------------------------------------
/pdCalc/src/app/pdCalc/pdCalc.pro:
--------------------------------------------------------------------------------
1 | HOME = ../../..
2 | include ($$HOME/common.pri)
3 | TEMPLATE = app
4 | TARGET = pdCalc
5 | DEPENDPATH += .
6 | INCLUDEPATH += $$HOME/src
7 | DESTDIR = $$HOME/bin
8 |
9 | QT += widgets
10 |
11 | win32:CONFIG += console
12 |
13 | SOURCES += main.cpp
14 |
15 | unix:LIBS += -L$$HOME/lib -lpdCalcGui -lpdCalcCli -lpdCalcBackend -lpdCalcUtilities
16 | win32:LIBS += -L$$HOME/bin -lpdCalcGui1 -lpdCalcCli1 -lpdCalcBackend1 -lpdCalcUtilities1
17 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/AppObservers.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "AppObservers.h"
20 | #include "utilities/Exception.h"
21 | #include "ui/cli/Cli.h"
22 | #include "Stack.h"
23 | #include "utilities/UserInterface.h"
24 | #include
25 | #include
26 |
27 | using std::ostringstream;
28 | using std::shared_ptr;
29 | using std::dynamic_pointer_cast;
30 | using std::vector;
31 |
32 | namespace pdCalc {
33 |
34 | CommandIssuedObserver::CommandIssuedObserver(CommandDispatcher& ce)
35 | : Observer("CommandIssued")
36 | , ce_(ce)
37 | { }
38 |
39 | void CommandIssuedObserver::notifyImpl(std::shared_ptr eventData)
40 | {
41 | auto data = dynamic_pointer_cast(eventData);
42 | if(!data)
43 | {
44 | throw Exception("Could not convert CommandData to a command");
45 | }
46 | else
47 | {
48 | ce_.commandEntered( data->command() );
49 | }
50 |
51 | return;
52 | }
53 |
54 | StackUpdatedObserver::StackUpdatedObserver(UserInterface& ui)
55 | : Observer("StackUpdated")
56 | , ui_(ui)
57 | { }
58 |
59 | void StackUpdatedObserver::notifyImpl(std::shared_ptr)
60 | {
61 | ui_.stackChanged();
62 |
63 | return;
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/AppObservers.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef APP_OBSERVERS_H
20 | #define APP_OBSERVERS_H
21 |
22 | #include "utilities/Observer.h"
23 | #include "CommandDispatcher.h"
24 |
25 | namespace pdCalc {
26 |
27 | class UserInterface;
28 |
29 | class CommandIssuedObserver : public Observer
30 | {
31 | public:
32 | explicit CommandIssuedObserver(CommandDispatcher& ce);
33 |
34 | private:
35 | void notifyImpl(std::shared_ptr) override;
36 |
37 | CommandDispatcher& ce_;
38 | };
39 |
40 | class StackUpdatedObserver : public Observer
41 | {
42 | public:
43 | explicit StackUpdatedObserver(UserInterface& ui);
44 |
45 | private:
46 | void notifyImpl(std::shared_ptr) override;
47 |
48 | UserInterface& ui_;
49 | };
50 |
51 |
52 | }
53 | #endif
54 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/Command.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "Command.h"
20 | #include "Stack.h"
21 | #include "utilities/Exception.h"
22 |
23 | namespace pdCalc {
24 |
25 | void Command::execute()
26 | {
27 | checkPreconditionsImpl();
28 | executeImpl();
29 | return;
30 | }
31 |
32 | void Command::undo()
33 | {
34 | undoImpl();
35 | return;
36 | }
37 |
38 | Command* Command::clone() const
39 | {
40 | return cloneImpl();
41 | }
42 |
43 | const char* Command::helpMessage() const
44 | {
45 | return helpMessageImpl();
46 | }
47 |
48 | void Command::deallocate()
49 | {
50 | delete this;
51 | }
52 |
53 | void Command::checkPreconditionsImpl() const
54 | {
55 | return;
56 | }
57 |
58 | BinaryCommand::BinaryCommand(const BinaryCommand& rhs)
59 | : Command(rhs)
60 | , top_{rhs.top_}
61 | , next_{rhs.next_}
62 | { }
63 |
64 | BinaryCommand::~BinaryCommand()
65 | { }
66 |
67 | void BinaryCommand::checkPreconditionsImpl() const
68 | {
69 | if( Stack::Instance().size() < 2 )
70 | throw Exception{"Stack must have 2 elements"};
71 | }
72 |
73 | void BinaryCommand::executeImpl() noexcept
74 | {
75 | // suppress change signal so only one event raised for the execute
76 | top_ = Stack::Instance().pop(true);
77 | next_ = Stack::Instance().pop(true);
78 | Stack::Instance().push( binaryOperation(next_, top_) );
79 |
80 | return;
81 | }
82 |
83 | void BinaryCommand::undoImpl() noexcept
84 | {
85 | // suppress change signal so only one event raised for the execute
86 | Stack::Instance().pop(true);
87 | Stack::Instance().push(next_, true);
88 | Stack::Instance().push(top_);
89 |
90 | return;
91 | }
92 |
93 | UnaryCommand::UnaryCommand(const UnaryCommand& rhs)
94 | : Command(rhs)
95 | , top_(rhs.top_)
96 | {
97 | }
98 |
99 | UnaryCommand::~UnaryCommand()
100 | { }
101 |
102 | void UnaryCommand::checkPreconditionsImpl() const
103 | {
104 | if( Stack::Instance().size() < 1 )
105 | throw Exception{"Stack must have one element"};
106 | }
107 |
108 | void UnaryCommand::executeImpl() noexcept
109 | {
110 | // suppress change signal so only one event raised for the execute
111 | top_ = Stack::Instance().pop(true);
112 | Stack::Instance().push( unaryOperation(top_) );
113 |
114 | return;
115 | }
116 |
117 | void UnaryCommand::undoImpl() noexcept
118 | {
119 | // suppress change signal so only one event raised for the execute
120 | Stack::Instance().pop(true);
121 | Stack::Instance().push(top_);
122 |
123 | return;
124 | }
125 |
126 | PluginCommand::~PluginCommand()
127 | { }
128 |
129 | void PluginCommand::checkPreconditionsImpl() const
130 | {
131 | const char* p = checkPluginPreconditions();
132 | if(p) throw Exception(p);
133 |
134 | return;
135 | }
136 |
137 | PluginCommand *PluginCommand::cloneImpl() const
138 | {
139 | auto p = clonePluginImpl();
140 | if(!p) throw Exception("Problem cloning a plugin command");
141 | else return p;
142 | }
143 |
144 | BinaryCommandAlternative::BinaryCommandAlternative(const std::string& help, std::function f)
145 | : helpMsg_{help}
146 | , command_{f}
147 | { }
148 |
149 | void BinaryCommandAlternative::checkPreconditionsImpl() const
150 | {
151 | if( Stack::Instance().size() < 2 )
152 | throw Exception{"Stack must have 2 elements"};
153 | }
154 |
155 | BinaryCommandAlternative::BinaryCommandAlternative(const BinaryCommandAlternative& rhs)
156 | : Command{rhs}
157 | , top_{rhs.top_}
158 | , next_{rhs.next_}
159 | , helpMsg_{rhs.helpMsg_}
160 | , command_{rhs.command_}
161 | { }
162 |
163 | const char *BinaryCommandAlternative::helpMessageImpl() const noexcept
164 | {
165 | return helpMsg_.c_str();
166 | }
167 |
168 | BinaryCommandAlternative* BinaryCommandAlternative::cloneImpl() const
169 | {
170 | return new BinaryCommandAlternative{*this};
171 | }
172 |
173 | void BinaryCommandAlternative::executeImpl() noexcept
174 | {
175 | // suppress change signal so only one event raised for the execute
176 | top_ = Stack::Instance().pop(true);
177 | next_ = Stack::Instance().pop(true);
178 | Stack::Instance().push( command_(next_, top_) );
179 |
180 | return;
181 | }
182 |
183 | void BinaryCommandAlternative::undoImpl() noexcept
184 | {
185 | // suppress change signal so only one event raised for the execute
186 | Stack::Instance().pop(true);
187 | Stack::Instance().push(next_, true);
188 | Stack::Instance().push(top_);
189 |
190 | return;
191 | }
192 |
193 |
194 | }
195 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/Command.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef COMMAND_H
20 | #define COMMAND_H
21 |
22 | #include
23 | #include
24 | #include
25 |
26 | namespace pdCalc {
27 |
28 | class Command
29 | {
30 | public:
31 | virtual ~Command() { }
32 |
33 | // executes the command
34 | void execute();
35 |
36 | // undoes the command
37 | void undo();
38 |
39 | // create a polymorphic copy of the command
40 | Command* clone() const;
41 |
42 | // supplies a short help message for the command
43 | const char* helpMessage() const;
44 |
45 | // Deletes commands. This should only be overridden in plugins. By default,
46 | // simply deletes command. In plugins, delete must happen in the plugin.
47 | virtual void deallocate();
48 |
49 | protected:
50 | Command() { }
51 | Command(const Command&) { }
52 |
53 | private:
54 | // this function is not pure virtual because a command that needs no preconditions
55 | // shouldn't be forced to check for any...thus, this defaults to not throwing
56 | virtual void checkPreconditionsImpl() const;
57 |
58 | virtual void executeImpl() noexcept = 0;
59 | virtual void undoImpl() noexcept = 0;
60 | virtual Command* cloneImpl() const = 0;
61 |
62 | // all commands should have a short help
63 | virtual const char* helpMessageImpl() const noexcept = 0;
64 |
65 | Command(Command&&) = delete;
66 | Command& operator=(const Command&) = delete;
67 | Command& operator=(Command&&) = delete;
68 | };
69 |
70 | // Base class for binary operations: take two elements from stack and return
71 | // one result. For any binary operation x and stack with top and next,
72 | // the binary operation is applied as next x top
73 | // Precondition: Binary operations must have at least two elements
74 | // on the stack
75 | // The reason to have a binary operations class is because undo,
76 | // redo, and preconditions can be implemented identically
77 | class BinaryCommand : public Command
78 | {
79 | public:
80 | virtual ~BinaryCommand();
81 |
82 | protected:
83 | // throws an exception if the stack size is less than two
84 | void checkPreconditionsImpl() const override;
85 |
86 | BinaryCommand() { }
87 | BinaryCommand(const BinaryCommand&);
88 |
89 | private:
90 | BinaryCommand(BinaryCommand&&) = delete;
91 | BinaryCommand& operator=(const BinaryCommand&) = delete;
92 | BinaryCommand& operator=(BinaryCommand&&) = delete;
93 |
94 | // takes two elements from the stack, applies the binary operation
95 | // and returns the result to the stack
96 | void executeImpl() noexcept override;
97 |
98 | // drops the result and returns the original two numbers to the stack
99 | void undoImpl() noexcept override;
100 |
101 | virtual double binaryOperation(double next, double top) const noexcept = 0;
102 |
103 | double top_;
104 | double next_;
105 | };
106 |
107 | // Base class for unary operations: take one element from the stack and return
108 | // one result.
109 | // Precondition: Unary operations must have at least one element on the stack.
110 | // The reason to have a unary operations class is to avoid repetition for
111 | // all classes implementing a unary interface.
112 | class UnaryCommand : public Command
113 | {
114 | public:
115 | virtual ~UnaryCommand();
116 |
117 | protected:
118 | // throws an exception if the stack size is less than one
119 | void checkPreconditionsImpl() const override;
120 |
121 | UnaryCommand() { }
122 | UnaryCommand(const UnaryCommand&);
123 |
124 | private:
125 | UnaryCommand(UnaryCommand&&) = delete;
126 | UnaryCommand& operator=(const UnaryCommand&) = delete;
127 | UnaryCommand& operator=(UnaryCommand&&) = delete;
128 |
129 | // takes one element from the stack, applies the binary operation
130 | // and returns the result to teh stack
131 | void executeImpl() noexcept override;
132 |
133 | // drops the result and returns the original number to the stack
134 | void undoImpl() noexcept override;
135 |
136 | virtual double unaryOperation(double top) const noexcept = 0;
137 |
138 | double top_;
139 | };
140 |
141 | class PluginCommand : public Command
142 | {
143 | public:
144 | virtual ~PluginCommand();
145 |
146 | private:
147 | virtual const char* checkPluginPreconditions() const noexcept = 0;
148 | virtual PluginCommand* clonePluginImpl() const noexcept = 0;
149 |
150 | void checkPreconditionsImpl() const override final;
151 | PluginCommand* cloneImpl() const override final;
152 | };
153 |
154 | // This shows an entirely different design using function and lambdas.
155 | class BinaryCommandAlternative final : public Command
156 | {
157 | using BinaryCommandOp = double(double, double);
158 | public:
159 | BinaryCommandAlternative(const std::string& help, std::function f);
160 | ~BinaryCommandAlternative() = default;
161 |
162 | private:
163 | BinaryCommandAlternative(BinaryCommandAlternative&&) = delete;
164 | BinaryCommandAlternative& operator=(const BinaryCommandAlternative&) = delete;
165 | BinaryCommandAlternative& operator=(BinaryCommandAlternative&&) = delete;
166 |
167 | // throws an exception if the stack size is less than two
168 | void checkPreconditionsImpl() const override;
169 |
170 | BinaryCommandAlternative(const BinaryCommandAlternative&);
171 |
172 | const char* helpMessageImpl() const noexcept override;
173 |
174 | // takes two elements from the stack, applies the binary operation
175 | // and returns the result to the stack
176 | void executeImpl() noexcept override;
177 |
178 | // drops the result and returns the original two numbers to the stack
179 | void undoImpl() noexcept override;
180 |
181 | BinaryCommandAlternative* cloneImpl() const override;
182 |
183 | double top_;
184 | double next_;
185 | std::string helpMsg_;
186 | std::function command_;
187 | };
188 |
189 | inline void CommandDeleter(Command* p)
190 | {
191 | p->deallocate();
192 | return;
193 | }
194 |
195 | using CommandPtr = std::unique_ptr;
196 |
197 | template
198 | auto MakeCommandPtr(Args&&... args)
199 | {
200 | return CommandPtr{new T{std::forward(args)...}, &CommandDeleter};
201 | }
202 |
203 | inline auto MakeCommandPtr(Command* p)
204 | {
205 | return CommandPtr{p, &CommandDeleter};
206 | }
207 |
208 | }
209 |
210 | #endif
211 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/CommandDispatcher.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "CommandDispatcher.h"
20 | #include "CommandRepository.h"
21 | #include "CommandManager.h"
22 | #include "CoreCommands.h"
23 | #include "utilities/Exception.h"
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include "utilities/UserInterface.h"
29 | #include
30 | #include "utilities/Tokenizer.h"
31 | #include "StoredProcedure.h"
32 |
33 | using std::string;
34 | using std::ostringstream;
35 | using std::unique_ptr;
36 | using std::set;
37 | using std::istringstream;
38 |
39 | namespace pdCalc {
40 |
41 | class CommandDispatcher::CommandDispatcherImpl
42 | {
43 | public:
44 | explicit CommandDispatcherImpl(UserInterface& ui);
45 |
46 | void executeCommand(const string& command);
47 |
48 |
49 | private:
50 | bool isNum(const string&, double& d);
51 | void handleCommand(CommandPtr command);
52 | void printHelp() const;
53 |
54 | CommandManager manager_;
55 | UserInterface& ui_;
56 | };
57 |
58 | CommandDispatcher::CommandDispatcherImpl::CommandDispatcherImpl(UserInterface& ui)
59 | : ui_(ui)
60 | { }
61 |
62 | void CommandDispatcher::CommandDispatcherImpl::executeCommand(const string& command)
63 | {
64 | // entry of a number simply goes onto the the stack
65 | double d;
66 | if( isNum(command, d) )
67 | manager_.executeCommand(MakeCommandPtr(d));
68 | else if(command == "undo")
69 | manager_.undo();
70 | else if(command == "redo")
71 | manager_.redo();
72 | else if(command == "help")
73 | printHelp();
74 | else if(command.size() > 6 && command.substr(0, 5) == "proc:")
75 | {
76 | auto filename = command.substr(5, command.size() - 5);
77 | handleCommand( MakeCommandPtr(ui_, filename) );
78 | }
79 | else
80 | {
81 | auto c = CommandRepository::Instance().allocateCommand(command);
82 | if(!c)
83 | {
84 | ostringstream oss;
85 | oss << "Command " << command << " is not a known command";
86 | ui_.postMessage( oss.str() );
87 | }
88 | else handleCommand( std::move(c) );
89 | }
90 |
91 | return;
92 | }
93 |
94 | void CommandDispatcher::CommandDispatcherImpl::handleCommand(CommandPtr c)
95 | {
96 | try
97 | {
98 | manager_.executeCommand( std::move(c) );
99 | }
100 | catch(Exception& e)
101 | {
102 | ui_.postMessage( e.what() );
103 | }
104 |
105 | return;
106 | }
107 |
108 | void CommandDispatcher::CommandDispatcherImpl::printHelp() const
109 | {
110 | ostringstream oss;
111 | set allCommands = CommandRepository::Instance().getAllCommandNames();
112 | oss << "\n";
113 | oss << "undo: undo last operation\n"
114 | << "redo: redo last operation\n";
115 |
116 | for(auto i : allCommands)
117 | {
118 | CommandRepository::Instance().printHelp(i, oss);
119 | oss << "\n";
120 | }
121 |
122 | ui_.postMessage( oss.str() );
123 |
124 | }
125 |
126 | // uses a C++11 regular expression to check if this is a valid double number
127 | // if so, converts it into one and returns it
128 | bool CommandDispatcher::CommandDispatcherImpl::isNum(const string& s, double& d)
129 | {
130 | if(s == "+" || s == "-") return false;
131 |
132 | std::regex dpRegex("((\\+|-)?[[:digit:]]*)(\\.(([[:digit:]]+)?))?((e|E)((\\+|-)?)[[:digit:]]+)?");
133 | bool isNumber{ std::regex_match(s, dpRegex) };
134 |
135 | if(isNumber)
136 | {
137 | d = std::stod(s);
138 | }
139 |
140 | return isNumber;
141 | }
142 |
143 | void CommandDispatcher::commandEntered(const std::string& command)
144 | {
145 | pimpl_->executeCommand(command);
146 |
147 | return;
148 | }
149 |
150 | CommandDispatcher::CommandDispatcher(UserInterface& ui)
151 | {
152 | pimpl_ = std::make_unique(ui);
153 | }
154 |
155 | CommandDispatcher::~CommandDispatcher()
156 | { }
157 |
158 | }
159 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/CommandDispatcher.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef COMMAND_DISPATCHER_H
20 | #define COMMAND_DISPATCHER_H
21 |
22 | #include
23 | #include
24 | #include "Command.h"
25 | #include
26 |
27 | namespace pdCalc {
28 |
29 | class UserInterface;
30 |
31 | class CommandDispatcher
32 | {
33 | class CommandDispatcherImpl;
34 |
35 | public:
36 | explicit CommandDispatcher(UserInterface& ui);
37 | ~CommandDispatcher();
38 |
39 | void commandEntered(const std::string& command);
40 |
41 | private:
42 | CommandDispatcher(const CommandDispatcher&) = delete;
43 | CommandDispatcher(CommandDispatcher&&) = delete;
44 | CommandDispatcher& operator=(const CommandDispatcher&) = delete;
45 | CommandDispatcher& operator=(CommandDispatcher&&) = delete;
46 |
47 |
48 | std::unique_ptr pimpl_;
49 | };
50 |
51 | }
52 |
53 | #endif
54 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/CommandManager.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef COMMAND_MANAGER_H
20 | #define COMMAND_MANAGER_H
21 |
22 | #include
23 | #include "Command.h"
24 |
25 | namespace pdCalc {
26 |
27 | class CommandManager
28 | {
29 | class CommandManagerImpl;
30 | class UndoRedoStackStrategy;
31 | class UndoRedoListStrategyVector;
32 | class UndoRedoListStrategy;
33 | public:
34 | enum class UndoRedoStrategy { ListStrategy, StackStrategy, ListStrategyVector };
35 |
36 | explicit CommandManager(UndoRedoStrategy st = UndoRedoStrategy::StackStrategy);
37 | ~CommandManager();
38 |
39 | size_t getUndoSize() const;
40 | size_t getRedoSize() const;
41 |
42 | // This function call executes the command, enters the new command onto the undo stack,
43 | // and it clears the redo stack. This is consistent with typical undo/redo functionality.
44 | void executeCommand(CommandPtr c);
45 |
46 | // This function undoes the command at the top of the undo stack and moves this command
47 | // to the redo stack. It does nothing if the undo stack is empty.
48 | void undo();
49 |
50 | // This function executes the command at the top of the redo stack and moves this command
51 | // to the undo stack. It does nothing if the redo stack is empty.
52 | void redo();
53 |
54 | private:
55 | CommandManager(CommandManager&) = delete;
56 | CommandManager(CommandManager&& ) = delete;
57 | CommandManager& operator=(CommandManager&) = delete;
58 | CommandManager& operator=(CommandManager&&) = delete;
59 |
60 | std::unique_ptr pimpl_;
61 | };
62 |
63 | }
64 |
65 | #endif
66 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/CommandRepository.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "CommandRepository.h"
20 | #include "Command.h"
21 | #include
22 | #include "../utilities/Exception.h"
23 | #include
24 |
25 | using std::string;
26 | using std::unordered_map;
27 | using std::set;
28 |
29 | namespace pdCalc {
30 |
31 | class CommandRepository::CommandRepositoryImpl
32 | {
33 | public:
34 | CommandRepositoryImpl();
35 | void registerCommand(const string& name, CommandPtr c);
36 | CommandPtr deregisterCommand(const string& name);
37 |
38 | size_t getNumberCommands() const { return repository_.size(); }
39 | CommandPtr allocateCommand(const string& name) const;
40 |
41 | bool hasKey(const string& s) const;
42 | set getAllCommandNames() const;
43 |
44 | void printHelp(const std::string& command, std::ostream& os);
45 |
46 | void clearAllCommands();
47 |
48 | private:
49 | using Repository = unordered_map;
50 | Repository repository_;
51 | };
52 |
53 | CommandRepository::CommandRepositoryImpl::CommandRepositoryImpl()
54 | {
55 | }
56 |
57 | bool CommandRepository::CommandRepositoryImpl::hasKey(const string& s) const
58 | {
59 | return repository_.find(s) != repository_.end();
60 | }
61 |
62 | set CommandRepository::CommandRepositoryImpl::getAllCommandNames() const
63 | {
64 | set tmp;
65 |
66 | for(auto i = repository_.begin(); i != repository_.end(); ++i)
67 | tmp.insert(i->first);
68 |
69 | return tmp;
70 | }
71 |
72 | void CommandRepository::CommandRepositoryImpl::printHelp(const std::string& command, std::ostream& os)
73 | {
74 | auto it = repository_.find(command);
75 | if(it != repository_.end())
76 | os << command << ": " << it->second->helpMessage();
77 | else
78 | os << command << ": no help entry found";
79 |
80 | return;
81 | }
82 |
83 | void CommandRepository::CommandRepositoryImpl::clearAllCommands()
84 | {
85 | repository_.clear();
86 | return;
87 | }
88 |
89 | void CommandRepository::CommandRepositoryImpl::registerCommand(const string& name, CommandPtr c)
90 | {
91 | if( hasKey(name) )
92 | {
93 | std::ostringstream oss;
94 | oss << "Command " << name << " already registered";
95 | throw Exception{ oss.str() };
96 | }
97 | else
98 | repository_.emplace( name, std::move(c) );
99 |
100 | return;
101 | }
102 |
103 | CommandPtr CommandRepository::CommandRepositoryImpl::deregisterCommand(const string& name)
104 | {
105 | if( hasKey(name) )
106 | {
107 | auto i = repository_.find(name);
108 | auto tmp = MakeCommandPtr( i->second.release() );
109 | repository_.erase(i);
110 | return tmp;
111 | }
112 | else return MakeCommandPtr(nullptr);
113 | }
114 |
115 | CommandPtr CommandRepository::CommandRepositoryImpl::allocateCommand(const string &name) const
116 | {
117 | if( hasKey(name) )
118 | {
119 | const auto& command = repository_.find(name)->second;
120 | return MakeCommandPtr( command->clone() );
121 | }
122 | else return MakeCommandPtr(nullptr);
123 | }
124 |
125 | CommandRepository::CommandRepository()
126 | : pimpl_{ new CommandRepositoryImpl }
127 | {
128 | }
129 |
130 | CommandRepository::~CommandRepository()
131 | { }
132 |
133 | CommandRepository& CommandRepository::Instance()
134 | {
135 | static CommandRepository instance;
136 | return instance;
137 | }
138 |
139 | void CommandRepository::registerCommand(const string& name, CommandPtr c)
140 | {
141 | pimpl_->registerCommand( name, std::move(c) );
142 |
143 | return;
144 | }
145 | CommandPtr CommandRepository::deregisterCommand(const string& name)
146 | {
147 | return pimpl_->deregisterCommand(name);
148 | }
149 |
150 | size_t CommandRepository::getNumberCommands() const
151 | {
152 | return pimpl_->getNumberCommands();
153 | }
154 |
155 | CommandPtr CommandRepository::allocateCommand(const string& name) const
156 | {
157 | return pimpl_->allocateCommand(name);
158 | }
159 |
160 | bool CommandRepository::hasKey(const string& s) const
161 | {
162 | return pimpl_->hasKey(s);
163 | }
164 |
165 | set CommandRepository::getAllCommandNames() const
166 | {
167 | return pimpl_->getAllCommandNames();
168 | }
169 |
170 | void CommandRepository::printHelp(const std::string& command, std::ostream& os) const
171 | {
172 | pimpl_->printHelp(command, os);
173 | return;
174 | }
175 |
176 | void CommandRepository::clearAllCommands()
177 | {
178 | pimpl_->clearAllCommands();
179 | return;
180 | }
181 |
182 | }
183 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/CommandRepository.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef COMMAND_REPOSITORY_H
20 | #define COMMAND_REPOSITORY_H
21 |
22 | // The CommandRepository class is responsible for returning a Command by name. New commands
23 | // can be dynamically added at runtime (to support) plugins, and commands can also be
24 | // deregistered (if desired if a plugin is removed). New commands are returned as clones
25 | // of the registered Command. This makes use of the Prototype pattern.
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include "Command.h"
32 |
33 | namespace pdCalc {
34 |
35 | class CommandRepository
36 | {
37 | class CommandRepositoryImpl;
38 | public:
39 | static CommandRepository& Instance();
40 |
41 | // register a new command for the factory: throws if a command with the
42 | // same name already exists...deregister first to replace a command
43 | void registerCommand(const std::string& name, CommandPtr c);
44 |
45 | // deregister a command: returns the pointer to a command and subsequently
46 | // removes it from the internal database of commands...returns a nullptr
47 | // if the command does not exist
48 | CommandPtr deregisterCommand(const std::string& name);
49 |
50 | // returns the number of commands currently registered
51 | size_t getNumberCommands() const;
52 |
53 | // returns a pointer to a command without deregistering the command...returns
54 | // a nullptr if the command does not exist
55 | CommandPtr allocateCommand(const std::string& name) const;
56 |
57 | // returns true if the command is present, false otherwise
58 | bool hasKey(const std::string& s) const;
59 |
60 | // returns a set of all the commands
61 | std::set getAllCommandNames() const;
62 |
63 | // prints help for command
64 | void printHelp(const std::string& command, std::ostream&) const;
65 |
66 | // clears all commands; mainly needed for testing
67 | void clearAllCommands();
68 |
69 | private:
70 | CommandRepository();
71 | ~CommandRepository();
72 |
73 | CommandRepository(CommandRepository&) = delete;
74 | CommandRepository(CommandRepository&&) = delete;
75 | CommandRepository& operator=(CommandRepository&) = delete;
76 | CommandRepository& operator=(CommandRepository&&) = delete;
77 |
78 | std::unique_ptr pimpl_;
79 | };
80 |
81 | }
82 | #endif
83 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/DynamicLoader.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "DynamicLoader.h"
20 |
21 | namespace pdCalc {
22 |
23 | DynamicLoader::~DynamicLoader()
24 | {
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/DynamicLoader.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef DYNAMIC_LOADER_H
20 | #define DYNAMIC_LOADER_H
21 |
22 | // This is the base class to abstract OS specific dynamic library loading.
23 | // Loading should be the same in any POSIX compliant OS (e.g., Linux, Mac OS X,
24 | // BSD). Windows loads dynamic libraries differently.
25 |
26 | // Note, this class specifies that Plugins must have a function named AllocPlugin with
27 | // signature
28 | // pdCalc::Plugin* AllocPlugin()
29 | // that allocates a pdCalc::Plugin with the global new function. The pdCalc::Plugin base
30 | // class is defined in a separate header.
31 |
32 | #include
33 |
34 | namespace pdCalc {
35 |
36 | class Plugin;
37 |
38 | class DynamicLoader
39 | {
40 | public:
41 | virtual ~DynamicLoader();
42 |
43 | // derived class must provide an OS specific way of loading a shared library,
44 | // dynamically binding to the AllocPlugin function in the plugin, allocating the
45 | // plugin, and closing the plugin
46 | virtual Plugin* allocatePlugin(const std::string& pluginName) = 0;
47 | virtual void deallocatePlugin(Plugin*) = 0;
48 |
49 | // Get the plugin allocation name for derived classes
50 | static const std::string GetPluginAllocationName() { return "AllocPlugin"; }
51 | static const std::string GetPluginDeallocationName() { return "DeallocPlugin"; }
52 | };
53 |
54 | }
55 |
56 | // function pointer for the interface to allocate a plugin
57 | extern "C" { typedef void* (*PluginAllocator)(void); }
58 |
59 | // function pointer for the interface to deallocate a plugin
60 | extern "C" { typedef void (*PluginDeallocator)(void*); }
61 | #endif
62 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/PlatformFactory.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "PlatformFactory.h"
20 |
21 | #ifdef POSIX
22 | #include "PosixFactory.h"
23 | #elif WIN32
24 | #include "WindowsFactory.h"
25 | #endif
26 |
27 | namespace pdCalc {
28 |
29 | PlatformFactory::PlatformFactory()
30 | {
31 | }
32 |
33 | PlatformFactory& PlatformFactory::Instance()
34 | {
35 | #ifdef POSIX
36 | static PosixFactory instance;
37 | #elif WIN32
38 | static WindowsFactory instance;
39 | #endif
40 |
41 | return instance;
42 | }
43 |
44 | PlatformFactory::~PlatformFactory()
45 | {
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/PlatformFactory.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef PLATFORM_FACTORY_H
20 | #define PLATFORM_FACTORY_H
21 |
22 | #include
23 |
24 | namespace pdCalc {
25 |
26 | class DynamicLoader;
27 |
28 | class PlatformFactory
29 | {
30 | public:
31 | static PlatformFactory& Instance();
32 | virtual ~PlatformFactory();
33 |
34 | virtual std::unique_ptr createDynamicLoader() = 0;
35 |
36 | protected:
37 | PlatformFactory();
38 |
39 | private:
40 | PlatformFactory(const PlatformFactory&) = delete;
41 | PlatformFactory& operator=(const PlatformFactory&) = delete;
42 | PlatformFactory(PlatformFactory&&) = delete;
43 | PlatformFactory& operator=(PlatformFactory&&) = delete;
44 | };
45 |
46 | }
47 |
48 | #endif
49 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/Plugin.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef PLUGIN_H
20 | #define PLUGIN_H
21 |
22 | // This is the base class to extend pdCalc with plugin commands. The plugin
23 | // must provide a command with its name (for the command structure), which
24 | // automatically provides a CLI interface. Optionally, a plugin can provide
25 | // a GUI interface.
26 |
27 | #include "Command.h"
28 |
29 | namespace pdCalc {
30 |
31 | class CommandButton;
32 |
33 | // Plugins are responsible for deleting the memory in the descriptors
34 | class Plugin
35 | {
36 | public:
37 | Plugin() { }
38 | virtual ~Plugin() { }
39 |
40 | struct PluginDescriptor
41 | {
42 | int nCommands;
43 | char** commandNames;
44 | Command** commands;
45 | };
46 |
47 | virtual const PluginDescriptor& getPluginDescriptor() const = 0;
48 |
49 | struct PluginButtonDescriptor
50 | {
51 | int nButtons;
52 | char** dispPrimaryCmd;
53 | char** primaryCmd;
54 | char** dispShftCmd;
55 | char** shftCmd;
56 | };
57 |
58 | // pointer instead of reference so that nullptr can be returned if buttons are not provided
59 | virtual const PluginButtonDescriptor* getPluginButtonDescriptor() const = 0;
60 |
61 | struct ApiVersion
62 | {
63 | int major;
64 | int minor;
65 | };
66 |
67 | virtual ApiVersion apiVersion() const = 0;
68 |
69 | private:
70 | Plugin(const Plugin&) = delete;
71 | Plugin& operator=(const Plugin&) = delete;
72 | Plugin(Plugin&&) = delete;
73 | Plugin& operator=(Plugin&&) = delete;
74 | };
75 |
76 | }
77 | #endif
78 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/PluginLoader.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "PluginLoader.h"
20 | #include "utilities/UserInterface.h"
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include "DynamicLoader.h"
26 | #include "Plugin.h"
27 | #include "PlatformFactory.h"
28 |
29 | using std::vector;
30 | using std::string;
31 | using std::ifstream;
32 | using std::unique_ptr;
33 |
34 | namespace pdCalc {
35 |
36 | class PluginDeleter
37 | {
38 | public:
39 | explicit PluginDeleter(DynamicLoader& d) : loader_{d} {}
40 | void operator()(Plugin* p) { loader_.deallocatePlugin(p); }
41 |
42 | private:
43 | DynamicLoader& loader_;
44 | };
45 |
46 | class PluginLoader::PluginLoaderImpl
47 | {
48 | public:
49 | PluginLoaderImpl();
50 |
51 | void loadPlugins(UserInterface& ui, const string& pluginFileName);
52 | const vector getPlugins();
53 |
54 | private:
55 | void load(UserInterface& ui, const string&);
56 |
57 | vector> loaders_;
58 | vector> plugins_;
59 | };
60 |
61 | PluginLoader::PluginLoaderImpl::PluginLoaderImpl()
62 | {
63 | }
64 |
65 | void PluginLoader::PluginLoaderImpl::loadPlugins(UserInterface& ui, const string& pluginFileName)
66 | {
67 | ifstream ifs{ pluginFileName.c_str() };
68 | if(!ifs)
69 | {
70 | ui.postMessage("Could not open plugin file");
71 | }
72 | else
73 | {
74 | vector pluginNames{ std::istream_iterator(ifs), std::istream_iterator() };
75 |
76 | for(auto i : pluginNames) load(ui, i);
77 | }
78 |
79 | return;
80 | }
81 |
82 | const vector PluginLoader::PluginLoaderImpl::getPlugins()
83 | {
84 | vector v;
85 | for(auto& i : plugins_)
86 | v.push_back( i.get() );
87 |
88 | return v;
89 | }
90 |
91 | void PluginLoader::PluginLoaderImpl::load(UserInterface& ui, const string& name)
92 | {
93 | loaders_.emplace_back( PlatformFactory::Instance().createDynamicLoader() );
94 |
95 | // may be null
96 | auto p = loaders_.back()->allocatePlugin(name);
97 | if(p) plugins_.emplace_back( p, PluginDeleter( *loaders_.back() ) );
98 | else ui.postMessage("Error opening plugin");
99 |
100 | return;
101 | }
102 |
103 | PluginLoader::PluginLoader()
104 | : pimpl_{ new PluginLoaderImpl }
105 | { }
106 |
107 | PluginLoader::~PluginLoader()
108 | { }
109 |
110 | void PluginLoader::loadPlugins(UserInterface& ui, const string& pluginFileName)
111 | {
112 | pimpl_->loadPlugins(ui, pluginFileName);
113 | return;
114 | }
115 |
116 | const std::vector PluginLoader::getPlugins()
117 | {
118 | return pimpl_->getPlugins();
119 | }
120 |
121 | }
122 |
123 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/PluginLoader.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef PLUGIN_LOADER_H
20 | #define PLUGIN_LOADER_H
21 |
22 | // This class can load the plugins specified in a file.
23 | // The file has the path and name of the plugins specified
24 | // on separate lines.
25 | // If a plugin cannot be loaded, the loader fails informs
26 | // the UI but ignores the error.
27 |
28 | #include
29 | #include
30 | #include
31 |
32 | namespace pdCalc {
33 |
34 | class Plugin;
35 | class UserInterface;
36 |
37 | class PluginLoader
38 | {
39 | class PluginLoaderImpl;
40 | public:
41 | PluginLoader();
42 | ~PluginLoader();
43 |
44 | void loadPlugins(UserInterface& ui, const std::string& pluginFileName);
45 | const std::vector getPlugins();
46 |
47 | private:
48 | PluginLoader(const PluginLoader&) = delete;
49 | PluginLoader(PluginLoader&&) = delete;
50 | PluginLoader& operator=(const PluginLoader&) = delete;
51 | PluginLoader& operator=(PluginLoader&&) = delete;
52 |
53 | std::unique_ptr pimpl_;
54 | };
55 |
56 | }
57 |
58 | #endif
59 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/PosixDynamicLoader.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "PosixDynamicLoader.h"
20 | #include "utilities/Exception.h"
21 | #include
22 | #include
23 | #include
24 |
25 | using std::cout;
26 | using std::endl;
27 |
28 | namespace pdCalc {
29 |
30 | PosixDynamicLoader::PosixDynamicLoader()
31 | : DynamicLoader{}
32 | , handle_{nullptr}
33 | {
34 | }
35 |
36 | PosixDynamicLoader::~PosixDynamicLoader()
37 | {
38 | if(handle_) dlclose(handle_);
39 | }
40 |
41 | Plugin* PosixDynamicLoader::allocatePlugin(const std::string& pluginName)
42 | {
43 | handle_ = dlopen(pluginName.c_str(), RTLD_LAZY);
44 |
45 | if(!handle_) return nullptr;
46 | else
47 | {
48 | auto alloc = dlsym(handle_, GetPluginAllocationName().c_str());
49 | PluginAllocator allocator{ reinterpret_cast(alloc) };
50 | if(allocator)
51 | {
52 | auto p = static_cast((*allocator)());
53 | return p;
54 | }
55 | else return nullptr;
56 | }
57 |
58 | return nullptr;
59 | }
60 |
61 | void PosixDynamicLoader::deallocatePlugin(Plugin* p)
62 | {
63 | if(!handle_)
64 | throw Exception("Trying to deallocate a plugin, but shared library is not open.");
65 | else
66 | {
67 | auto dealloc = dlsym(handle_, GetPluginDeallocationName().c_str());
68 | auto deallocator = reinterpret_cast(dealloc);
69 | if(deallocator)
70 | {
71 | (*deallocator)(p);
72 | }
73 | else throw Exception("Could not load the deallocator function in the plugin");
74 | }
75 |
76 | return;
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/PosixDynamicLoader.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef POSIX_DYNAMIC_LOADER_H
20 | #define POSIX_DYNAMIC_LOADER_H
21 |
22 | #include
23 | #include "DynamicLoader.h"
24 |
25 | namespace pdCalc {
26 |
27 | class PosixDynamicLoader : public DynamicLoader
28 | {
29 | public:
30 | PosixDynamicLoader();
31 | ~PosixDynamicLoader();
32 |
33 | Plugin* allocatePlugin(const std::string& pluginName) override;
34 | void deallocatePlugin(Plugin* p) override;
35 |
36 | private:
37 | void* handle_;
38 | };
39 |
40 | }
41 |
42 | #endif // POSIXDYNAMICLOADER_H
43 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/PosixFactory.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "PosixFactory.h"
20 | #include "PosixDynamicLoader.h"
21 |
22 | using std::unique_ptr;
23 |
24 | namespace pdCalc {
25 |
26 | PosixFactory::PosixFactory()
27 | {
28 | }
29 |
30 | unique_ptr PosixFactory::createDynamicLoader()
31 | {
32 | return std::make_unique();
33 | }
34 |
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/PosixFactory.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef POSIX_FACTORY_H
20 | #define POSIX_FACTORY_H
21 |
22 | #include "PlatformFactory.h"
23 | #include
24 |
25 | namespace pdCalc {
26 |
27 | class PosixFactory : public PlatformFactory
28 | {
29 | public:
30 | PosixFactory();
31 |
32 | std::unique_ptr createDynamicLoader() override;
33 | };
34 |
35 | }
36 |
37 | #endif
38 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/Stack.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "Stack.h"
20 | #include "utilities/Exception.h"
21 | #include
22 |
23 | using std::vector;
24 | using std::string;
25 |
26 | namespace pdCalc {
27 |
28 | const string Stack::StackChanged = "stackChanged";
29 | const string Stack::StackError = "error";
30 |
31 | const char* StackEventData::Message(StackEventData::ErrorConditions ec)
32 | {
33 | switch(ec)
34 | {
35 | case ErrorConditions::Empty: return "Attempting to pop empty stack";
36 | case ErrorConditions::TooFewArguments: return "Need at least two stack elements to swap top";
37 | default: return "Unknown error";
38 | };
39 | }
40 |
41 | const char* StackEventData::message() const
42 | {
43 | return Message(err_);
44 | }
45 |
46 | class Stack::StackImpl
47 | {
48 | public:
49 | explicit StackImpl(const Stack&);
50 | void push(double d, bool suppressChangeEvent);
51 | double pop(bool suppressChangeEvent);
52 | void swapTop();
53 | vector getElements(size_t n) const;
54 | void getElements(size_t n, vector& v) const;
55 | size_t size() const { return stack_.size(); }
56 | void clear();
57 | double top() const;
58 |
59 | private:
60 | const Stack& parent_; // for raising events
61 | std::deque stack_;
62 | };
63 |
64 | Stack::StackImpl::StackImpl(const Stack& s)
65 | : parent_(s)
66 | {
67 |
68 | }
69 |
70 | void Stack::StackImpl::push(double d, bool suppressChangeEvent)
71 | {
72 | stack_.push_back(d);
73 | if(!suppressChangeEvent) parent_.raise(Stack::StackChanged, nullptr);
74 |
75 | return;
76 | }
77 |
78 | double Stack::StackImpl::pop(bool suppressChangeEvent)
79 | {
80 | if( stack_.empty() )
81 | {
82 | parent_.raise(Stack::StackError,
83 | std::make_shared(StackEventData::ErrorConditions::Empty));
84 |
85 | throw Exception{StackEventData::Message(StackEventData::ErrorConditions::Empty)};
86 | }
87 | else
88 | {
89 | auto val = stack_.back();
90 | stack_.pop_back();
91 | if(!suppressChangeEvent) parent_.raise(Stack::StackChanged, nullptr);
92 | return val;
93 | }
94 | }
95 |
96 | void Stack::StackImpl::swapTop()
97 | {
98 | if( stack_.size() < 2 )
99 | {
100 | parent_.raise(Stack::StackError,
101 | std::make_shared(StackEventData::ErrorConditions::TooFewArguments));
102 |
103 | throw Exception{StackEventData::Message(StackEventData::ErrorConditions::TooFewArguments)};
104 | }
105 | else
106 | {
107 | auto first = stack_.back();
108 | stack_.pop_back();
109 | auto second = stack_.back();
110 | stack_.pop_back();
111 | stack_.push_back(first);
112 | stack_.push_back(second);
113 |
114 | parent_.raise(Stack::StackChanged, nullptr);
115 | }
116 |
117 | return;
118 | }
119 |
120 | vector Stack::StackImpl::getElements(size_t n) const
121 | {
122 | vector v;
123 | getElements(n, v);
124 | return v;
125 | }
126 |
127 | void Stack::StackImpl::getElements(size_t n, vector& v) const
128 | {
129 | // if n is > stack's size, just return size of stack
130 | if(n > stack_.size()) n = stack_.size();
131 |
132 | v.insert(v.end(), stack_.rbegin(), stack_.rbegin() + n);
133 |
134 | return;
135 | }
136 |
137 | void Stack::StackImpl::clear()
138 | {
139 | stack_.clear();
140 |
141 | parent_.raise(Stack::StackChanged, nullptr);
142 |
143 | return;
144 | }
145 |
146 | double Stack::StackImpl::top() const
147 | {
148 | return stack_.back();
149 | }
150 |
151 | Stack& Stack::Instance()
152 | {
153 | static Stack instance;
154 | return instance;
155 | }
156 |
157 | void Stack::push(double d, bool suppressChangeEvent)
158 | {
159 | pimpl_->push(d, suppressChangeEvent);
160 | return;
161 | }
162 |
163 | double Stack::pop(bool suppressChangeEvent)
164 | {
165 | return pimpl_->pop(suppressChangeEvent);
166 | }
167 |
168 | void Stack::swapTop()
169 | {
170 | pimpl_->swapTop();
171 | return;
172 | }
173 |
174 | vector Stack::getElements(size_t n) const
175 | {
176 | return pimpl_->getElements(n);
177 | }
178 |
179 | void Stack::getElements(size_t n, vector& v) const
180 | {
181 | pimpl_->getElements(n, v);
182 | return;
183 | }
184 |
185 | size_t Stack::size() const
186 | {
187 | return pimpl_->size();
188 | }
189 |
190 | void Stack::clear() const
191 | {
192 | pimpl_->clear();
193 | return;
194 | }
195 |
196 | Stack::Stack()
197 | {
198 | pimpl_ = std::make_unique(*this);
199 | registerEvent(StackChanged);
200 | registerEvent(StackError);
201 | }
202 |
203 | Stack::~Stack()
204 | {
205 |
206 | }
207 |
208 | }
209 |
210 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/Stack.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef STACK_H
20 | #define STACK_H
21 |
22 | #include "../utilities/Publisher.h"
23 | #include
24 | #include
25 | #include
26 |
27 | namespace pdCalc {
28 |
29 | class StackEventData : public EventData
30 | {
31 | public:
32 | enum class ErrorConditions { Empty, TooFewArguments };
33 | explicit StackEventData(ErrorConditions e) : err_(e) { }
34 |
35 | static const char* Message(ErrorConditions ec);
36 | const char* message() const;
37 | ErrorConditions error() const { return err_; }
38 |
39 | private:
40 | ErrorConditions err_;
41 | };
42 |
43 | class Stack : private Publisher
44 | {
45 | class StackImpl; // so that the implementation can raise events
46 |
47 | public:
48 | static Stack& Instance();
49 | void push(double, bool suppressChangeEvent = false);
50 | double pop(bool suppressChangeEvent = false);
51 | void swapTop();
52 |
53 | // returns first min(n, stackSize) elements of the stack with the top of stack at position 0
54 | std::vector getElements(size_t n) const;
55 | void getElements(size_t n, std::vector&) const;
56 |
57 | using Publisher::attach;
58 | using Publisher::detach;
59 |
60 | // these are just needed for testing
61 | size_t size() const;
62 | void clear() const;
63 |
64 | static const std::string StackChanged;
65 | static const std::string StackError;
66 |
67 | private:
68 | Stack();
69 | ~Stack();
70 | Stack(const Stack&) = delete;
71 | Stack(Stack&&) = delete;
72 | Stack& operator=(const Stack&) = delete;
73 | Stack& operator=(const Stack&&) = delete;
74 |
75 | std::unique_ptr pimpl_;
76 | };
77 |
78 | }
79 |
80 | #endif
81 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/StackPluginInterface.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "Stack.h"
20 | #include "StackPluginInterface.h"
21 |
22 | using std::vector;
23 |
24 | void StackPush(double d, bool suppressChangeEvent)
25 | {
26 | pdCalc::Stack::Instance().push(d, suppressChangeEvent);
27 |
28 | return;
29 | }
30 |
31 | double StackPop(bool suppressChangeEvent)
32 | {
33 | return pdCalc::Stack::Instance().pop(suppressChangeEvent);
34 | }
35 |
36 | size_t StackSize()
37 | {
38 | return pdCalc::Stack::Instance().size();
39 | }
40 |
41 | double StackFirstElement()
42 | {
43 | vector v = pdCalc::Stack::Instance().getElements(1);
44 | return v[0];
45 | }
46 |
47 | double StackSecondElement()
48 | {
49 | vector v = pdCalc::Stack::Instance().getElements(2);
50 | return v[1];
51 | }
52 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/StackPluginInterface.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef STACK_PLUGIN_INTERFACE_H
20 | #define STACK_PLUGIN_INTERFACE_H
21 |
22 | extern "C" void StackPush(double d, bool suppressChangeEvent);
23 | extern "C" double StackPop(bool suppressChangeEvent);
24 | extern "C" size_t StackSize();
25 | extern "C" double StackFirstElement();
26 | extern "C" double StackSecondElement();
27 |
28 | #endif
29 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/StoredProcedure.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "StoredProcedure.h"
20 | #include "CommandDispatcher.h"
21 | #include "utilities/Exception.h"
22 | #include "utilities/Tokenizer.h"
23 | #include
24 |
25 | using std::string;
26 |
27 | namespace pdCalc {
28 |
29 | StoredProcedure::StoredProcedure(UserInterface& ui, const string& filename)
30 | : filename_{filename}
31 | {
32 | ce_ = std::make_unique(ui);
33 | }
34 |
35 | StoredProcedure::~StoredProcedure()
36 | { }
37 |
38 | void StoredProcedure::checkPreconditionsImpl() const
39 | {
40 | if(first_)
41 | {
42 | try
43 | {
44 | std::ifstream ifs{ filename_.c_str() };
45 | if(!ifs)
46 | throw Exception{"Could not open procedure"};
47 |
48 | tokenizer_ = std::make_unique(ifs);
49 | }
50 | catch(...)
51 | {
52 | throw Exception{"Could not open procedure"};
53 | }
54 | }
55 |
56 | return;
57 | }
58 |
59 | void StoredProcedure::executeImpl() noexcept
60 | {
61 | if(first_)
62 | {
63 | for(auto c : *tokenizer_)
64 | {
65 | ce_->commandEntered(c);
66 | }
67 | first_ = false;
68 | }
69 | else
70 | {
71 | for(unsigned int i = 0; i < tokenizer_->nTokens(); ++i)
72 | ce_->commandEntered("redo");
73 | }
74 |
75 | return;
76 | }
77 |
78 | void StoredProcedure::undoImpl() noexcept
79 | {
80 | for(unsigned int i = 0; i < tokenizer_->nTokens(); ++i)
81 | ce_->commandEntered("undo");
82 |
83 | return;
84 | }
85 |
86 | Command*StoredProcedure::cloneImpl() const noexcept
87 | {
88 | return 0;
89 | }
90 |
91 | const char* StoredProcedure::helpMessageImpl() const noexcept
92 | {
93 | return "Executes a stored procedure from disk";
94 | }
95 |
96 | }
97 |
98 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/StoredProcedure.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef STORED_PROCEDURE_H
20 | #define STORED_PROCEDURE_H
21 |
22 | #include "Command.h"
23 | #include "utilities/Tokenizer.h"
24 | #include
25 | #include
26 |
27 | namespace pdCalc {
28 |
29 | class CommandDispatcher;
30 | class UserInterface;
31 |
32 | class StoredProcedure : public Command
33 | {
34 | public:
35 | StoredProcedure(UserInterface& ui, const std::string& filename);
36 | ~StoredProcedure();
37 |
38 | private:
39 | StoredProcedure() = delete;
40 | StoredProcedure(StoredProcedure&&) = delete;
41 | StoredProcedure& operator=(const StoredProcedure&) = delete;
42 | StoredProcedure& operator=(StoredProcedure&&) = delete;
43 | StoredProcedure(const StoredProcedure&) = delete;
44 |
45 | void checkPreconditionsImpl() const override;
46 | void executeImpl() noexcept override;
47 | void undoImpl() noexcept override;
48 | Command* cloneImpl() const noexcept override;
49 | const char* helpMessageImpl() const noexcept override;
50 |
51 | mutable std::unique_ptr tokenizer_;
52 | std::unique_ptr ce_;
53 | std::string filename_;
54 | bool first_ = true;
55 | };
56 |
57 | }
58 |
59 | #endif
60 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/WindowsDynamicLoader.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "WindowsDynamicLoader.h"
20 | #include
21 | #include
22 | #include "utilities/Exception.h"
23 |
24 | using std::wstring;
25 | using std::string;
26 | using std::vector;
27 |
28 | namespace {
29 | wstring toWstring(const string& s)
30 | {
31 | vector ws(s.size());
32 | std::mbstowcs(&ws[0], s.c_str(), s.size());
33 | return wstring{ws.begin(), ws.end()};
34 | }
35 |
36 | }
37 |
38 | namespace pdCalc {
39 |
40 | WindowsDynamicLoader::WindowsDynamicLoader()
41 | : DynamicLoader{}
42 | , handle_{nullptr}
43 | {
44 |
45 | }
46 |
47 | WindowsDynamicLoader::~WindowsDynamicLoader()
48 | {
49 | if(handle_) FreeLibrary(handle_);
50 | }
51 |
52 | Plugin* WindowsDynamicLoader::allocatePlugin(const std::string& pluginName)
53 | {
54 | wstring wPluginName = toWstring(pluginName);
55 | handle_ = LoadLibrary(wPluginName.c_str());
56 |
57 | if(!handle_) return nullptr;
58 | else
59 | {
60 | auto alloc = GetProcAddress(handle_, GetPluginAllocationName().c_str());
61 | PluginAllocator allocator{ reinterpret_cast(alloc) };
62 | if(allocator)
63 | {
64 | auto p = static_cast((*allocator)());
65 | return p;
66 | }
67 | else return nullptr;
68 | }
69 | }
70 |
71 | void WindowsDynamicLoader::deallocatePlugin(Plugin* p)
72 | {
73 | if(!handle_)
74 | throw Exception("Trying to deallocate a plugin, but shared library is not open.");
75 | else
76 | {
77 | auto dealloc = GetProcAddress(handle_, GetPluginDeallocationName().c_str());
78 | auto deallocator = reinterpret_cast(dealloc);
79 | if(deallocator)
80 | {
81 | (*deallocator)(p);
82 | }
83 | else throw Exception("Could not load the deallocator function in the plugin");
84 | }
85 |
86 | return;
87 | }
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/WindowsDynamicLoader.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef WINDOWS_DYNAMIC_LOADER_H
20 | #define WINDOWS_DYNAMIC_LOADER_H
21 |
22 | #include
23 | #include
24 | #include "DynamicLoader.h"
25 |
26 | namespace pdCalc {
27 |
28 | class WindowsDynamicLoader : public DynamicLoader
29 | {
30 | public:
31 | WindowsDynamicLoader();
32 | ~WindowsDynamicLoader();
33 |
34 | Plugin* allocatePlugin(const std::string& pluginName) override;
35 | void deallocatePlugin(Plugin* p) override;
36 |
37 | private:
38 | HINSTANCE handle_;
39 | };
40 |
41 | }
42 |
43 | #endif
44 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/WindowsFactory.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "WindowsFactory.h"
20 | #include "WindowsDynamicLoader.h"
21 |
22 | namespace pdCalc {
23 |
24 | WindowsFactory::WindowsFactory()
25 | { }
26 |
27 | std::unique_ptr WindowsFactory::createDynamicLoader()
28 | {
29 | return std::make_unique();
30 | }
31 |
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/WindowsFactory.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef WINDOWS_FACTORY_H
20 | #define WINDOWS_FACTORY_H
21 |
22 | #include "PlatformFactory.h"
23 | #include
24 |
25 | namespace pdCalc {
26 |
27 | class WindowsFactory : public PlatformFactory
28 | {
29 | public:
30 | WindowsFactory();
31 |
32 | std::unique_ptr createDynamicLoader() override;
33 | };
34 |
35 | }
36 |
37 | #endif
38 |
--------------------------------------------------------------------------------
/pdCalc/src/backend/backend.pro:
--------------------------------------------------------------------------------
1 | HOME = ../..
2 | include ($$HOME/common.pri)
3 | TEMPLATE = lib
4 | TARGET = pdCalcBackend
5 | DEPENDPATH += .
6 | INCLUDEPATH += . $$HOME/src
7 | unix:DESTDIR = $$HOME/lib
8 | win32:DESTDIR = $$HOME/bin
9 |
10 |
11 | win32:DEFINES += _USE_MATH_DEFINES
12 |
13 | # Input
14 | HEADERS += Stack.h \
15 | StackPluginInterface.h \
16 | Command.h \
17 | CommandManager.h \
18 | CommandRepository.h \
19 | CommandDispatcher.h \
20 | CoreCommands.h \
21 | StoredProcedure.h \
22 | PluginLoader.h \
23 | DynamicLoader.h \
24 | Plugin.h \
25 | PlatformFactory.h \
26 | StackPluginInterface.h \
27 | AppObservers.h
28 |
29 | unix:HEADERS += PosixDynamicLoader.h \
30 | PosixFactory.h
31 |
32 | win32:HEADERS += WindowsDynamicLoader.h \
33 | WindowsFactory.h
34 |
35 | SOURCES += Stack.cpp \
36 | StackPluginInterface.cpp \
37 | CommandManager.cpp \
38 | CommandRepository.cpp \
39 | CommandDispatcher.cpp \
40 | Command.cpp \
41 | CoreCommands.cpp \
42 | StoredProcedure.cpp \
43 | PluginLoader.cpp \
44 | DynamicLoader.cpp \
45 | PlatformFactory.cpp \
46 | AppObservers.cpp
47 |
48 | unix:SOURCES += PosixDynamicLoader.cpp \
49 | PosixFactory.cpp
50 |
51 | win32:SOURCES += WindowsDynamicLoader.cpp \
52 | WindowsFactory.cpp
53 |
54 | unix:LIBS += -ldl
55 | win32:LIBS += -L$$HOME/bin -lpdCalcUtilities1
56 |
--------------------------------------------------------------------------------
/pdCalc/src/plugins/hyperbolicLnPlugin/HyperbolicLnPlugin.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef HYPERBOLIC_LN_PLUGIN_H
20 | #define HYPERBOLIC_LN_PLUGIN_H
21 |
22 | #include
23 | #include
24 | #include "backend/Plugin.h"
25 |
26 | class HyperbolicLnPlugin : public pdCalc::Plugin
27 | {
28 | class HyperbolicLnPluginImpl;
29 | public:
30 | HyperbolicLnPlugin();
31 | ~HyperbolicLnPlugin();
32 |
33 | const PluginDescriptor& getPluginDescriptor() const override;
34 | const PluginButtonDescriptor* getPluginButtonDescriptor() const override;
35 | pdCalc::Plugin::ApiVersion apiVersion() const;
36 |
37 | private:
38 | std::unique_ptr pimpl_;
39 | };
40 |
41 | extern "C" void* AllocPlugin();
42 | extern "C" void DeallocPlugin(void*);
43 |
44 | #endif
45 |
--------------------------------------------------------------------------------
/pdCalc/src/plugins/hyperbolicLnPlugin/hyperbolicLnPlugin.pro:
--------------------------------------------------------------------------------
1 | HOME = ../../..
2 | include ($$HOME/common.pri)
3 | TEMPLATE = lib
4 | TARGET = hyperbolicLnPlugin
5 | DEPENDPATH += .
6 | INCLUDEPATH += . $$HOME/src
7 | unix:DESTDIR = $$HOME/lib
8 | win32:DESTDIR = $$HOME/bin
9 | QT += widgets
10 |
11 | # Input
12 | HEADERS += HyperbolicLnPlugin.h
13 | SOURCES += HyperbolicLnPlugin.cpp
14 |
15 | unix:QMAKE_PRE_LINK+=$(COPY_FILE) $$PWD/../plugins.pdp.unix $$HOME/bin/plugins.pdp
16 | win32:QMAKE_PRE_LINK+=$(COPY_FILE) $$shell_path($$PWD/../plugins.pdp.win) $$shell_path($$HOME/bin/plugins.pdp)
17 |
18 | win32:LIBS += -L$$HOME/bin -lpdCalcUtilities1 -lpdCalcBackend1
19 |
--------------------------------------------------------------------------------
/pdCalc/src/plugins/plugins.pdp.unix:
--------------------------------------------------------------------------------
1 | ../lib/libhyperbolicLnPlugin.so
2 |
--------------------------------------------------------------------------------
/pdCalc/src/plugins/plugins.pdp.win:
--------------------------------------------------------------------------------
1 | hyperbolicLnPlugin1.dll
2 |
--------------------------------------------------------------------------------
/pdCalc/src/plugins/plugins.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = subdirs
2 |
3 | SUBDIRS += hyperbolicLnPlugin
4 |
--------------------------------------------------------------------------------
/pdCalc/src/src.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = subdirs
2 |
3 | SUBDIRS += utilities \
4 | backend \
5 | ui/cli \
6 | ui/gui \
7 | app \
8 | plugins
9 |
--------------------------------------------------------------------------------
/pdCalc/src/ui/cli/Cli.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "Cli.h"
20 | #include "utilities/Tokenizer.h"
21 | #include "backend/Stack.h"
22 | #include
23 | #include
24 |
25 | using std::vector;
26 | using std::string;
27 | using std::istream;
28 | using std::ostream;
29 | using std::endl;
30 | using std::ostringstream;
31 |
32 | namespace pdCalc {
33 |
34 | class Cli::CliImpl
35 | {
36 | public:
37 | CliImpl(Cli&, istream& in, ostream& out);
38 | void postMessage(const string& m);
39 | void execute(bool suppressStartupMessage, bool echo);
40 | void stackChanged();
41 |
42 | private:
43 | void startupMessage();
44 |
45 | Cli& parent_;
46 | istream& in_;
47 | ostream& out_;
48 | };
49 |
50 | Cli::CliImpl::CliImpl(Cli& p, istream& in, ostream& out)
51 | : parent_(p)
52 | , in_(in)
53 | , out_(out)
54 | {
55 | }
56 |
57 | void Cli::CliImpl::postMessage(const string& m)
58 | {
59 | out_ << m << endl;
60 | return;
61 | }
62 |
63 | void Cli::CliImpl::startupMessage()
64 | {
65 | out_ << "pdCalc v. " << PDCALC_VERSION << ", an RPN calculator\n"
66 | << "type 'help' for a list of commnads\n"
67 | << "'exit' to end program\n" << endl;
68 |
69 | return;
70 | }
71 |
72 | void Cli::CliImpl::execute(bool suppressStartupMessage, bool echo)
73 | {
74 | if(!suppressStartupMessage) startupMessage();
75 |
76 | for(string line; std::getline(in_, line, '\n'); )
77 | {
78 | Tokenizer tokenizer{line};
79 | for(const auto& i : tokenizer)
80 | {
81 | if(echo) out_ << i << endl;
82 | if(i == "exit" || i == "quit")
83 | {
84 | return;
85 | }
86 | else
87 | {
88 | parent_.raise(UserInterface::CommandEntered, std::make_shared(i));
89 | }
90 | }
91 | }
92 |
93 | return;
94 | }
95 |
96 | void Cli::CliImpl::stackChanged()
97 | {
98 | unsigned int nElements{4};
99 | auto v = Stack::Instance().getElements(nElements);
100 | ostringstream oss;
101 | oss.precision(12);
102 | size_t size = Stack::Instance().size();
103 | oss << "\n";
104 | if(size == 0)
105 | oss << "Stack currently empty.\n";
106 | else if(size == 1)
107 | oss << "Top element of stack (size = " << size << "):\n";
108 | else if(size > 1 && size <= nElements)
109 | oss << "Top " << size << " elements of stack (size = " << size << "):\n";
110 | else
111 | oss << "Top " << nElements << " elements of stack (size = " << size << "):\n";
112 |
113 | size_t j{ v.size() };
114 | for(auto i = v.rbegin(); i != v.rend(); ++i)
115 | {
116 | oss << j << ":\t" << *i << "\n";
117 | --j;
118 | }
119 |
120 | postMessage( oss.str() );
121 | }
122 |
123 | Cli::Cli(istream& in, ostream& out)
124 | {
125 | pimpl_ = std::make_unique(*this, in, out);
126 | }
127 |
128 | Cli::~Cli()
129 | { }
130 |
131 | void Cli::postMessage(const string& m)
132 | {
133 | pimpl_->postMessage(m);
134 | return;
135 | }
136 |
137 | void Cli::stackChanged()
138 | {
139 | pimpl_->stackChanged();
140 | return;
141 | }
142 |
143 | void Cli::execute(bool suppressStartupMessage, bool echo)
144 | {
145 | pimpl_->execute(suppressStartupMessage, echo);
146 |
147 | return;
148 | }
149 |
150 | }
151 |
--------------------------------------------------------------------------------
/pdCalc/src/ui/cli/Cli.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef CLI_H
20 | #define CLI_H
21 |
22 | #include "utilities/UserInterface.h"
23 | #include
24 | #include
25 | #include
26 |
27 | namespace pdCalc {
28 |
29 | class Cli : public UserInterface
30 | {
31 | class CliImpl;
32 | public:
33 | Cli(std::istream&, std::ostream&);
34 | ~Cli();
35 |
36 | // start the cli run loop
37 | void execute(bool suppressStartupMessage = false, bool echo = false);
38 |
39 | private:
40 | // posts a text message to the output
41 | void postMessage(const std::string& m) override;
42 |
43 | // updates the output when the stack is changed
44 | void stackChanged() override;
45 |
46 | Cli(const Cli&) = delete;
47 | Cli(Cli&&) = delete;
48 | Cli& operator=(const Cli&) = delete;
49 | Cli& operator=(Cli&&) = delete;
50 |
51 | std::unique_ptr pimpl_;
52 | };
53 |
54 | }
55 |
56 | #endif
57 |
--------------------------------------------------------------------------------
/pdCalc/src/ui/cli/cli.pro:
--------------------------------------------------------------------------------
1 | HOME = ../../..
2 | include ($$HOME/common.pri)
3 | TEMPLATE = lib
4 | TARGET = pdCalcCli
5 | DEPENDPATH += .
6 | INCLUDEPATH += . $$HOME/src
7 | unix:DESTDIR = $$HOME/lib
8 | win32:DESTDIR = $$HOME/bin
9 |
10 |
11 | # Input
12 | HEADERS += Cli.h
13 | SOURCES += Cli.cpp
14 |
15 | win32:LIBS += -L$$HOME/bin -lpdCalcUtilities1 -lpdCalcBackend1
16 |
--------------------------------------------------------------------------------
/pdCalc/src/ui/gui/CommandButton.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "CommandButton.h"
20 | #include "LookAndFeel.h"
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 |
29 | using std::ostringstream;
30 | using std::cout;
31 | using std::endl;
32 |
33 | using std::string;
34 |
35 | namespace pdCalc {
36 |
37 | CommandButton::CommandButton(const string& dispPrimaryCmd, const string& primaryCmd,
38 | const string& dispShftCmd, const string& shftCmd, QWidget* parent)
39 | : QWidget{parent}
40 | , primaryCmd_{primaryCmd}
41 | , shftCmd_{shftCmd}
42 | {
43 | setup(dispPrimaryCmd, dispShftCmd);
44 | }
45 |
46 | CommandButton::CommandButton(const std::string& dispPrimaryCmd, const std::string& primaryCmd, QWidget* parent)
47 | : QWidget{parent}
48 | , primaryCmd_{primaryCmd}
49 | , shftCmd_{""}
50 | {
51 | setup(dispPrimaryCmd, "");
52 | }
53 |
54 | void CommandButton::registerShortcut(const QKeySequence& sequence)
55 | {
56 | // Use the shortcut mechanism rather than btn_->setShortcut() to allow
57 | // multiple different shortcuts for one button (e.g., plus/minus button)
58 | // shortcuts with both p and m. btn_->setShortcut() releases the current
59 | // shortcut when the next one is set.
60 |
61 | auto sc = new QShortcut(sequence, btn_);
62 | connect(sc, SIGNAL(activated()), this, SLOT(onClicked()));
63 | }
64 |
65 | void CommandButton::registerToolTip(const string& s)
66 | {
67 | btn_->setToolTip( QString::fromStdString(s) );
68 | return;
69 | }
70 |
71 | void CommandButton::setButtonTextColor(const std::string& color)
72 | {
73 | ostringstream oss;
74 | oss << "QPushButton { color : " << color << "; }";
75 | btn_->setStyleSheet( oss.str().c_str() );
76 |
77 | return;
78 | }
79 |
80 | void CommandButton::onClicked()
81 | {
82 | emit clicked(primaryCmd_, shftCmd_);
83 | }
84 |
85 | void CommandButton::setup(const std::string& dispPrimaryCmd, const std::string& dispShftCmd)
86 | {
87 | btn_ = new QPushButton{ QString::fromStdString(dispPrimaryCmd), this};
88 | btn_->setFont( LookAndFeel::Instance().getButtonFont() );
89 | btn_->setFixedSize( LookAndFeel::Instance().getMinimumButtonSize() );
90 |
91 | auto label = new QLabel{ QString::fromStdString(dispShftCmd), this };
92 | label->setFont( LookAndFeel::Instance().getShiftLabelFont() );
93 | label->setMinimumSize( ( dispShftCmd.empty() ? QSize(0, 0) : LookAndFeel::Instance().getMinimumShiftLabelSize()) );
94 |
95 | ostringstream oss;
96 | oss << "QLabel { color : " << LookAndFeel::Instance().getShiftColor() <<"; }";
97 | label->setStyleSheet( oss.str().c_str() );
98 |
99 | connect(btn_, SIGNAL(clicked()), this, SLOT(onClicked()));
100 |
101 | auto layout = new QVBoxLayout{this};
102 | layout->setSpacing(0);
103 | layout->addWidget(label);
104 | layout->addWidget(btn_);
105 | layout->setContentsMargins( LookAndFeel::Instance().getContentsMargins() );
106 | }
107 |
108 | }
109 |
--------------------------------------------------------------------------------
/pdCalc/src/ui/gui/CommandButton.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef COMMANDBUTTON_H
20 | #define COMMANDBUTTON_H
21 |
22 | #include
23 | #include
24 |
25 | class QPushButton;
26 |
27 | namespace pdCalc {
28 |
29 | // Class capable of emitting a signal with the primary and shift commands when the
30 | // button is clicked. Note that the receiver is responsible for figuring out if the
31 | // calculator is in shifted state.
32 | class CommandButton : public QWidget
33 | {
34 | Q_OBJECT
35 | public:
36 | // Initialize the button with the primary command to be displayed, the string commanad
37 | // this triggers, the shift command to be displayed, and the string command the
38 | // shift triggers
39 | CommandButton(const std::string& dispPrimaryCmd, const std::string& primaryCmd,
40 | const std::string& dispShftCmd, const std::string& shftCmd, QWidget* parent = nullptr);
41 |
42 | CommandButton(const std::string& dispPrimaryCmd, const std::string& primaryCmd,
43 | QWidget* parent = nullptr);
44 |
45 | // registers a keyboard shortcut
46 | void registerShortcut(const QKeySequence &sequence);
47 |
48 | // enter a tooltip so that hovering over the button will cause text to be displayed,
49 | // presumably the text will be the keyboard shortuct
50 | void registerToolTip(const std::string& s);
51 |
52 | // change button color (used, for example, for a shift button)
53 | void setButtonTextColor(const std::string& color);
54 |
55 | private slots:
56 | void onClicked();
57 |
58 | signals:
59 | void clicked(std::string primCmd, std::string shftCmd);
60 |
61 | private:
62 | void setup(const std::string& dispPrimaryCmd, const std::string& dispShftCommand);
63 |
64 | std::string primaryCmd_;
65 | std::string shftCmd_;
66 |
67 | QPushButton* btn_;
68 | };
69 |
70 | }
71 |
72 | #endif // COMMANDBUTTON_H
73 |
--------------------------------------------------------------------------------
/pdCalc/src/ui/gui/Display.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "Display.h"
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include "LookAndFeel.h"
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include "GuiModel.h"
32 |
33 | using std::vector;
34 | using std::ostringstream;
35 | using std::string;
36 |
37 | namespace pdCalc {
38 |
39 | class Display::DisplayImpl : public QWidget
40 | {
41 | public:
42 | explicit DisplayImpl(const GuiModel&, int nLinesStack, int nCharWide, QVBoxLayout* layout, Display* parent);
43 | string getText() const;
44 | void showMessage(const string& m);
45 | void onModelChanged();
46 |
47 | private:
48 | void setupSize();
49 | void resizeEvent(QResizeEvent*) override;
50 | string createLine(int lineNumber, double value, int stackSize);
51 | QValidator::State validate(const string&);
52 |
53 | const GuiModel& guiModel_;
54 | QLabel* label_;
55 | int nLinesStack_;
56 | int nCharWide_;
57 | QStatusBar* statusBar_;
58 | unsigned int statusBarTimeout;
59 | QLabel* shiftIndicator_;
60 | };
61 |
62 | Display::DisplayImpl::DisplayImpl(const GuiModel& g, int nLinesStack, int nCharWide, QVBoxLayout* layout, Display* parent)
63 | : QWidget{parent}
64 | , guiModel_{g}
65 | , nLinesStack_{nLinesStack}
66 | , nCharWide_{nCharWide}
67 | , statusBarTimeout{3000}
68 | {
69 | statusBar_ = new QStatusBar{this};
70 | statusBar_->setFont( LookAndFeel::Instance().getStatusBarFont() );
71 | statusBar_->setSizeGripEnabled(false);
72 | statusBar_->setPalette( LookAndFeel::Instance().getStatusBarPalette() );
73 | shiftIndicator_ = new QLabel{"Shift", this};
74 | statusBar_->addPermanentWidget(shiftIndicator_);
75 | shiftIndicator_->hide();
76 |
77 | label_ = new QLabel{this};
78 |
79 | ostringstream oss;
80 | oss << "QLabel { background-color : " << LookAndFeel::Instance().getDisplayBackgroundColor() << "; "
81 | << "border : " << LookAndFeel::Instance().getDisplayBorderStyle() << "; "
82 | << "border-radius : " << LookAndFeel::Instance().getDisplayBorderRadius() << "}";
83 | label_->setStyleSheet( oss.str().c_str() );
84 |
85 | layout->addWidget(statusBar_);
86 | layout->addWidget(label_);
87 |
88 | label_->setFont( LookAndFeel::Instance().getDisplayFont() );
89 |
90 | setupSize();
91 |
92 | onModelChanged();
93 | }
94 |
95 | string Display::DisplayImpl::getText() const
96 | {
97 | return label_->text().toStdString();
98 | }
99 |
100 | void Display::DisplayImpl::showMessage(const string& m)
101 | {
102 | statusBar_->showMessage( QString::fromStdString(m), statusBarTimeout);
103 | return;
104 | }
105 |
106 | void Display::DisplayImpl::setupSize()
107 | {
108 | QFontMetrics fm{LookAndFeel::Instance().getDisplayFont()};
109 | label_->setFixedHeight( nLinesStack_ * fm.height() + 2);
110 | label_->setMinimumWidth( (nCharWide_ + 2) * fm.maxWidth() );
111 |
112 | return;
113 | }
114 |
115 | void Display::DisplayImpl::resizeEvent(QResizeEvent* event)
116 | {
117 | QFontMetrics fm{LookAndFeel::Instance().getDisplayFont()};
118 | int w{ event->size().width() };
119 | nCharWide_ = w / fm.maxWidth() - 2;
120 |
121 | onModelChanged();
122 |
123 | return;
124 | }
125 |
126 | string Display::DisplayImpl::createLine(int lineNumber, double sv, int stackSize)
127 | {
128 | string value{""};
129 | if(lineNumber < stackSize)
130 | {
131 | ostringstream t;
132 | t.precision(12);
133 | t << sv;
134 | value = t.str();
135 | }
136 |
137 | ostringstream oss;
138 | oss << lineNumber + 1 << ":";
139 | int lineLabelSize{ static_cast(oss.str().size()) };
140 | for(int i = 0; i < nCharWide_ - static_cast( value.length() ) - lineLabelSize; ++i)
141 | {
142 | oss << ' ';
143 | }
144 | oss << value;
145 | return oss.str();
146 | }
147 |
148 | void Display::DisplayImpl::onModelChanged()
149 | {
150 | const GuiModel::State& state = guiModel_.getState();
151 | if(state.shiftState == GuiModel::ShiftState::Shifted)
152 | {
153 | shiftIndicator_->show();
154 | }
155 | else shiftIndicator_->hide();
156 |
157 | ostringstream oss;
158 | auto hasInput = state.curInput.size() != 0;
159 | auto start = nLinesStack_ - ( hasInput ? 1 : 0 );
160 |
161 | for(int i = start - 1; i > -1; --i)
162 | {
163 | bool valueExists = i < static_cast( state.curStack.size() );
164 | oss << createLine( i, (valueExists ? state.curStack[i] : 0 /*dummy value*/), state.curStack.size() ) << (i != 0 ? "\n" : "");
165 | }
166 |
167 | if(hasInput)
168 | {
169 | oss << "\n"
170 | << state.curInput;
171 | }
172 |
173 | label_->setText( QString::fromStdString( oss.str() ) );
174 | }
175 |
176 | Display::Display(const GuiModel& g, QWidget *parent, int nLinesStack, int nCharWide)
177 | : QWidget{parent}
178 | {
179 | auto layout = new QVBoxLayout{this};
180 | pimpl_ = new DisplayImpl{g, nLinesStack, nCharWide, layout, this};
181 | layout->setContentsMargins( LookAndFeel::Instance().getContentsMargins() );
182 | layout->addWidget(pimpl_);
183 | }
184 |
185 | std::string Display::getText() const
186 | {
187 | return pimpl_->getText();
188 | }
189 |
190 | void Display::showMessage(const std::string& m)
191 | {
192 | pimpl_->showMessage(m);
193 |
194 | return;
195 | }
196 |
197 | void Display::onModelChanged()
198 | {
199 | pimpl_->onModelChanged();
200 | }
201 |
202 |
203 | }
204 |
--------------------------------------------------------------------------------
/pdCalc/src/ui/gui/Display.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef DISPLAY_H
20 | #define DISPLAY_H
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | namespace pdCalc {
28 |
29 | class GuiModel;
30 |
31 | // This class is the calculator's display. It shows a number of lines of the stack
32 | // as determined by the constructor and shows the input as it is entered
33 |
34 | class Display : public QWidget
35 | {
36 | class DisplayImpl;
37 | Q_OBJECT
38 | public:
39 | // nLinesStack is the number of vertical lines of the stack to be displayed
40 | // minCharWide is the minimum number of characters wide for the display (defaults to min size)
41 | explicit Display(const GuiModel& g, QWidget* parent = nullptr, int nLinesStack = 6, int minCharWide = 25);
42 |
43 | // this is for testing purposes to be able to get the current display
44 | std::string getText() const;
45 |
46 | // show message in the status bar
47 | void showMessage(const std::string& m);
48 |
49 | public slots:
50 | // call this slot when the underlying model changes
51 | void onModelChanged();
52 |
53 | private:
54 | DisplayImpl* pimpl_;
55 |
56 | };
57 |
58 | }
59 |
60 | #endif
61 |
--------------------------------------------------------------------------------
/pdCalc/src/ui/gui/GuiModel.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef GUI_MODEL_H
20 | #define GUI_MODEL_H
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 | namespace pdCalc {
29 |
30 | class GuiModel : public QObject
31 | {
32 | class GuiModelImpl;
33 | Q_OBJECT
34 | public:
35 | enum class ShiftState { Unshifted, Shifted };
36 |
37 | struct State
38 | {
39 | State();
40 |
41 | std::vector curStack;
42 | std::string curInput;
43 | ShiftState shiftState;
44 | QValidator::State curInputValidity;
45 | };
46 |
47 | explicit GuiModel(QObject* parent = nullptr);
48 | ~GuiModel();
49 |
50 | void stackChanged(const std::vector& v);
51 |
52 | const State& getState() const;
53 |
54 | // exposed externally for testing only
55 | bool inputEmpty() const;
56 | void clearInput();
57 |
58 | public slots:
59 | // called to toggle the calculator's shift state
60 | void onShift();
61 |
62 | // call this slot when a new character of input is available
63 | void onCharacterEntered(char c);
64 |
65 | // call this slot when enter is pressed. Does nothing if input is invalid else enters number on stack
66 | // and clears input
67 | void onEnter();
68 |
69 | // call this slot to backspace during input entry
70 | void onBackspace();
71 |
72 | // call this slot when plus/minus is entered
73 | void onPlusMinus();
74 |
75 | // called when commands are entered
76 | void onCommandEntered(std::string primaryCmd, std::string secondaryCmd);
77 |
78 | signals:
79 | void modelChanged();
80 | void commandEntered(std::string s);
81 | void errorDetected(std::string s);
82 |
83 | private:
84 | std::unique_ptr pimpl_;
85 | };
86 |
87 | }
88 | #endif
89 |
--------------------------------------------------------------------------------
/pdCalc/src/ui/gui/InputWidget.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef INPUT_WIDGET_H
20 | #define INPUT_WIDGET_H
21 |
22 | #include
23 | #include
24 | #include
25 |
26 | class QGridLayout;
27 |
28 | namespace pdCalc {
29 |
30 | class InputWidget : public QWidget
31 | {
32 | class InputWidgetImpl;
33 | Q_OBJECT
34 | public:
35 | explicit InputWidget(QWidget *parent = nullptr);
36 | ~InputWidget();
37 |
38 | void addCommandButton(const std::string& dispPrimaryCmd, const std::string& primaryCmd,
39 | const std::string& dispShftCmd, const std::string& shftCmd);
40 |
41 | void setupFinalButtons();
42 |
43 | signals:
44 | void characterEntered(char c);
45 | void enterPressed();
46 | void backspacePressed();
47 | void plusMinusPressed();
48 | void commandEntered(std::string, std::string);
49 | void shiftPressed();
50 | void procedurePressed();
51 |
52 | private:
53 | std::unique_ptr pimpl_;
54 | };
55 |
56 | }
57 |
58 | #endif
59 |
--------------------------------------------------------------------------------
/pdCalc/src/ui/gui/LookAndFeel.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "LookAndFeel.h"
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 | using std::string;
29 |
30 | namespace pdCalc {
31 |
32 | class LookAndFeel::LookAndFeelImpl
33 | {
34 | public:
35 | LookAndFeelImpl();
36 | const QFont& getDisplayFont() const { return displayFont_; }
37 | const QFont& getButtonFont() const { return buttonFont_; }
38 | const QFont& getShiftLabelFont() const { return shiftLabelFont_; }
39 | const QFont& getStatusBarFont() const { return statusBarFont_; }
40 |
41 | const QSize& getMinimumButtonSize() const { return minButtonSize_; }
42 | const QSize& getMinimumShiftLabelSize() const { return minShiftLabelSize_; }
43 | const QPalette& getStatusBarPalette() const { return statusBarPalette_; }
44 | const QMargins& getContentsMargins() const { return contentsMargins_; }
45 | const string& getShiftColor() const { return shiftColor_; }
46 |
47 | private:
48 | void setupDisplayFont();
49 | void setupButtonFont();
50 | void setupShiftLabelFont();
51 | void setupStatusBarMetrics();
52 | void setupContentsMargins();
53 |
54 | QFont displayFont_;
55 | QFont buttonFont_;
56 | QFont shiftLabelFont_;
57 | QFont statusBarFont_;
58 | QPalette statusBarPalette_;
59 |
60 | QSize minButtonSize_;
61 | QSize minShiftLabelSize_;
62 |
63 | QMargins contentsMargins_;
64 |
65 | unsigned int displayFontPtSize_;
66 | string shiftColor_;
67 | QString fixedWidthFont_;
68 | };
69 |
70 | LookAndFeel::LookAndFeelImpl::LookAndFeelImpl()
71 | : displayFontPtSize_{14}
72 | , shiftColor_{"blue"}
73 | , fixedWidthFont_{"courier"}
74 | {
75 | setupDisplayFont();
76 | setupButtonFont();
77 | setupShiftLabelFont();
78 | setupStatusBarMetrics();
79 | setupContentsMargins();
80 | }
81 |
82 | void LookAndFeel::LookAndFeelImpl::setupDisplayFont()
83 | {
84 | displayFont_.setFamily(fixedWidthFont_);
85 | displayFont_.setPointSize(displayFontPtSize_);
86 |
87 | return;
88 | }
89 |
90 | void LookAndFeel::LookAndFeelImpl::setupButtonFont()
91 | {
92 | buttonFont_.setFamily(fixedWidthFont_);
93 | buttonFont_.setPointSize(displayFontPtSize_ - 2);
94 |
95 | QFontMetrics fm{buttonFont_};
96 | minButtonSize_.setHeight( 1.5 * fm.height() );
97 | minButtonSize_.setWidth( 6 * fm.maxWidth() );
98 |
99 | return;
100 | }
101 |
102 | void LookAndFeel::LookAndFeelImpl::setupShiftLabelFont()
103 | {
104 | shiftLabelFont_.setFamily(fixedWidthFont_);
105 | shiftLabelFont_.setPointSize(displayFontPtSize_ - 5);
106 |
107 | QFontMetrics fm{shiftLabelFont_};
108 | minShiftLabelSize_.setHeight( 1.5 * fm.height() );
109 | minShiftLabelSize_.setWidth( 6 * fm.maxWidth() );
110 | return;
111 | }
112 |
113 | void LookAndFeel::LookAndFeelImpl::setupStatusBarMetrics()
114 | {
115 | statusBarFont_.setFamily(fixedWidthFont_);
116 | statusBarFont_.setPointSize(displayFontPtSize_ - 4);
117 |
118 | statusBarPalette_.setColor(QPalette::WindowText, QColor(QString::fromStdString(shiftColor_)));
119 |
120 | return;
121 | }
122 |
123 | void LookAndFeel::LookAndFeelImpl::setupContentsMargins()
124 | {
125 | contentsMargins_.setTop(1);
126 | contentsMargins_.setBottom(1);
127 | contentsMargins_.setLeft(1);
128 | contentsMargins_.setRight(1);
129 |
130 | return;
131 | }
132 |
133 | const LookAndFeel& LookAndFeel::Instance()
134 | {
135 | static LookAndFeel instance;
136 | return instance;
137 | }
138 |
139 | const QFont &LookAndFeel::getDisplayFont() const
140 | {
141 | return pimpl_->getDisplayFont();
142 | }
143 |
144 | const QFont&LookAndFeel::getButtonFont() const
145 | {
146 | return pimpl_->getButtonFont();
147 | }
148 |
149 | const QFont&LookAndFeel::getShiftLabelFont() const
150 | {
151 | return pimpl_->getShiftLabelFont();
152 | }
153 |
154 | const QSize&LookAndFeel::getMinimumButtonSize() const
155 | {
156 | return pimpl_->getMinimumButtonSize();
157 | }
158 |
159 | const QSize&LookAndFeel::getMinimumShiftLabelSize() const
160 | {
161 | return pimpl_->getMinimumShiftLabelSize();
162 | }
163 |
164 | const QFont&LookAndFeel::getStatusBarFont() const
165 | {
166 | return pimpl_->getStatusBarFont();
167 | }
168 |
169 | const QPalette&LookAndFeel::getStatusBarPalette() const
170 | {
171 | return pimpl_->getStatusBarPalette();
172 | }
173 |
174 | const QMargins& LookAndFeel::getContentsMargins() const
175 | {
176 | return pimpl_->getContentsMargins();
177 | }
178 |
179 | const std::string& LookAndFeel::getShiftColor() const
180 | {
181 | return pimpl_->getShiftColor();
182 | }
183 |
184 | std::string LookAndFeel::getDisplayBackgroundColor() const
185 | {
186 | return "white";
187 | }
188 |
189 | std::string LookAndFeel::getDisplayBorderStyle() const
190 | {
191 | return "1px solid gray";
192 | }
193 |
194 | std::string LookAndFeel::getDisplayBorderRadius() const
195 | {
196 | return "6px";
197 | }
198 |
199 | LookAndFeel::LookAndFeel()
200 | : pimpl_{ new LookAndFeelImpl }
201 | { }
202 |
203 | LookAndFeel::~LookAndFeel()
204 | { }
205 |
206 | }
207 |
--------------------------------------------------------------------------------
/pdCalc/src/ui/gui/LookAndFeel.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef LOOK_AND_FEEL_H
20 | #define LOOK_AND_FEEL_H
21 |
22 | #include
23 |
24 | class QFont;
25 | class QSize;
26 | class QPalette;
27 | class QMargins;
28 |
29 | namespace pdCalc {
30 |
31 | // This is a singleton class that defines the metrics to be used by all
32 | // of the display. An example of such a metric would be a font family or
33 | // button size.
34 |
35 | class LookAndFeel
36 | {
37 | class LookAndFeelImpl;
38 | public:
39 | static const LookAndFeel& Instance();
40 |
41 | // get the font that should be used by the display
42 | const QFont& getDisplayFont() const;
43 |
44 | // get the font that should be used by the buttons
45 | const QFont& getButtonFont() const;
46 |
47 | // get the font that should be used by the shift labels for the buttons
48 | const QFont& getShiftLabelFont() const;
49 |
50 | // get the minimum size of the buttons
51 | const QSize& getMinimumButtonSize() const;
52 |
53 | // get the minimum size of the shift label
54 | const QSize& getMinimumShiftLabelSize() const;
55 |
56 | // get the font that should be used for the status bar
57 | const QFont& getStatusBarFont() const;
58 |
59 | // get the palette for the status bar to enable color change of status bar text
60 | const QPalette& getStatusBarPalette() const;
61 |
62 | // get contents margins for layouts affecting button spacing
63 | const QMargins& getContentsMargins() const;
64 |
65 | // get the color of the shift label
66 | const std::string& getShiftColor() const;
67 |
68 | // get display background color
69 | std::string getDisplayBackgroundColor() const;
70 |
71 | // get display border style
72 | std::string getDisplayBorderStyle() const;
73 |
74 | // get display border radius
75 | std::string getDisplayBorderRadius() const;
76 |
77 | private:
78 | LookAndFeel();
79 | ~LookAndFeel();
80 | LookAndFeel(const LookAndFeel&) = delete;
81 | LookAndFeel& operator=(const LookAndFeel&) = delete;
82 | LookAndFeel(LookAndFeel&&) = delete;
83 | LookAndFeel& operator=(LookAndFeel&&) = delete;
84 |
85 | std::unique_ptr pimpl_;
86 | };
87 |
88 | }
89 |
90 | #endif
91 |
--------------------------------------------------------------------------------
/pdCalc/src/ui/gui/MainWindow.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "MainWindow.h"
20 | #include "Display.h"
21 | #include "InputWidget.h"
22 | #include
23 | #include
24 | #include "backend/Stack.h"
25 | #include
26 | #include
27 | #include
28 | #include "LookAndFeel.h"
29 | #include "StoredProcedureDialog.h"
30 | #include
31 | #include "GuiModel.h"
32 |
33 | using std::ostringstream;
34 | using std::cout;
35 | using std::endl;
36 | using std::string;
37 | using std::vector;
38 |
39 | namespace pdCalc {
40 |
41 | class MainWindow::MainWindowImpl : public QWidget
42 | {
43 | Q_OBJECT
44 | public:
45 | explicit MainWindowImpl(MainWindow* parent);
46 | void showMessage(const string& m);
47 | void stackChanged();
48 | void setupFinalButtons();
49 | void addCommandButton(const std::string& dispPrimaryCmd, const std::string& primaryCmd, const std::string& dispShftCmd, const std::string& shftCmd);
50 |
51 | public slots:
52 | void onCommandEntered(std::string cmd);
53 | void onShowMessage(std::string m);
54 |
55 | private slots:
56 | void onProcedure();
57 |
58 | private:
59 | void connectInputToModel();
60 | void doLayout();
61 |
62 | MainWindow& parent_;
63 | int nLinesStack_;
64 | Display* display_;
65 | InputWidget* inputWidget_;
66 | GuiModel* guiModel_;
67 | };
68 |
69 | MainWindow::MainWindowImpl::MainWindowImpl(MainWindow* parent)
70 | : QWidget{parent}
71 | , parent_(*parent)
72 | , nLinesStack_{6}
73 | {
74 | guiModel_ = new GuiModel{this};
75 | display_ = new Display{*guiModel_, this, nLinesStack_};
76 |
77 | connect(guiModel_, SIGNAL(modelChanged()), display_, SLOT(onModelChanged()));
78 |
79 | inputWidget_ = new InputWidget{this};
80 |
81 | doLayout();
82 |
83 | connectInputToModel();
84 | }
85 |
86 | void MainWindow::MainWindowImpl::doLayout()
87 | {
88 | auto vblayout = new QVBoxLayout{this};
89 | vblayout->addWidget(display_);
90 | vblayout->addWidget(inputWidget_);
91 | vblayout->addStretch();
92 | }
93 |
94 | void MainWindow::MainWindowImpl::showMessage(const string& m)
95 | {
96 | display_->showMessage(m);
97 |
98 | return;
99 | }
100 |
101 | void MainWindow::MainWindowImpl::stackChanged()
102 | {
103 | auto v = Stack::Instance().getElements(nLinesStack_);
104 | guiModel_->stackChanged(v);
105 |
106 | return;
107 | }
108 |
109 | void MainWindow::MainWindowImpl::onProcedure()
110 | {
111 | StoredProcedureDialog dialog;
112 | if(dialog.exec() == QDialog::Accepted)
113 | {
114 | ostringstream oss;
115 | oss << "proc:" << dialog.getProcedure();
116 | guiModel_->onCommandEntered(oss.str(), "");
117 | }
118 |
119 | return;
120 | }
121 |
122 | void MainWindow::MainWindowImpl::connectInputToModel()
123 | {
124 | connect(inputWidget_, SIGNAL(backspacePressed()), guiModel_, SLOT(onBackspace()));
125 | connect(inputWidget_, SIGNAL(enterPressed()), guiModel_, SLOT(onEnter()));
126 | connect(inputWidget_, SIGNAL(characterEntered(char)), guiModel_, SLOT(onCharacterEntered(char)));
127 | connect(inputWidget_, SIGNAL(plusMinusPressed()), guiModel_, SLOT(onPlusMinus()));
128 | connect(inputWidget_, SIGNAL(commandEntered(std::string,std::string)), guiModel_, SLOT(onCommandEntered(std::string, std::string)));
129 | connect(inputWidget_, SIGNAL(procedurePressed()), this, SLOT(onProcedure()));
130 | connect(inputWidget_, SIGNAL(shiftPressed()), guiModel_, SLOT(onShift()));
131 | connect(guiModel_, SIGNAL(commandEntered(std::string)), this, SLOT(onCommandEntered(std::string)));
132 | connect(guiModel_, SIGNAL(errorDetected(std::string)), this, SLOT(onShowMessage(std::string)));
133 |
134 | return;
135 | }
136 |
137 | void MainWindow::MainWindowImpl::setupFinalButtons()
138 | {
139 | inputWidget_->setupFinalButtons();
140 | }
141 |
142 | void MainWindow::MainWindowImpl::addCommandButton(const string& dispPrimaryCmd, const string& primaryCmd,
143 | const string& dispShftCmd, const string& shftCmd)
144 | {
145 | inputWidget_->addCommandButton(dispPrimaryCmd, primaryCmd, dispShftCmd, shftCmd);
146 |
147 | return;
148 | }
149 |
150 | void MainWindow::MainWindowImpl::onCommandEntered(std::string cmd)
151 | {
152 | parent_.UserInterface::raise(UserInterface::CommandEntered, std::make_shared(cmd));
153 |
154 | return;
155 | }
156 |
157 | void MainWindow::MainWindowImpl::onShowMessage(std::string m)
158 | {
159 | showMessage(m);
160 | }
161 |
162 | MainWindow::MainWindow(int, char*[], QWidget* parent)
163 | : QMainWindow{parent}
164 | {
165 | pimpl_ = new MainWindowImpl{this};
166 | setCentralWidget(pimpl_);
167 | }
168 |
169 | void MainWindow::postMessage(const std::string& m)
170 | {
171 | pimpl_->showMessage(m);
172 |
173 | return;
174 | }
175 |
176 | void MainWindow::stackChanged()
177 | {
178 | pimpl_->stackChanged();
179 | }
180 |
181 | void MainWindow::addCommandButton(const string& dispPrimaryCmd, const string& primaryCmd,
182 | const string& dispShftCmd, const string& shftCmd)
183 | {
184 | pimpl_->addCommandButton(dispPrimaryCmd, primaryCmd, dispShftCmd, shftCmd);
185 | }
186 |
187 | void MainWindow::setupFinalButtons()
188 | {
189 | pimpl_->setupFinalButtons();
190 |
191 | return;
192 | }
193 |
194 | void MainWindow::fixSize()
195 | {
196 | setFixedSize( size() );
197 | }
198 |
199 | }
200 |
201 | #include "MainWindow.moc"
202 |
--------------------------------------------------------------------------------
/pdCalc/src/ui/gui/MainWindow.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef MAIN_WINDOW_H
20 | #define MAIN_WINDOW_H
21 |
22 | #include
23 | #include "utilities/UserInterface.h"
24 | #include
25 |
26 | namespace pdCalc {
27 |
28 | class CommandButton;
29 |
30 | class MainWindow : public QMainWindow, public UserInterface
31 | {
32 | class MainWindowImpl;
33 | public:
34 | MainWindow(int argc, char* argv[], QWidget* parent = nullptr);
35 |
36 | void postMessage(const std::string& m) override;
37 | void stackChanged() override;
38 |
39 | // Add a command button, for example, from a plugin
40 | // Buttons are added in order from left to right just below the
41 | // line undo, redo, proc from the bottom up
42 | // Buttons are reparented to MainWindow
43 | void addCommandButton(const std::string& dispPrimaryCmd, const std::string& primaryCmd, const std::string& dispShftCmd, const std::string& shftCmd);
44 |
45 | // setup the undo, redo, proc buttons after inserting plugin buttons
46 | void setupFinalButtons();
47 |
48 | // force the window to be fixed size...should be called as a final step once the GUI has fixed its own size
49 | void fixSize();
50 |
51 | private:
52 | MainWindowImpl* pimpl_;
53 | };
54 |
55 | }
56 |
57 | #endif
58 |
--------------------------------------------------------------------------------
/pdCalc/src/ui/gui/StoredProcedureDialog.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "StoredProcedureDialog.h"
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | namespace pdCalc {
28 |
29 | StoredProcedureDialog::StoredProcedureDialog(QWidget *parent)
30 | : QDialog{parent}
31 | {
32 | auto layout = new QVBoxLayout{this};
33 |
34 | auto label = new QLabel{"Enter procedure name:", this};
35 | layout->addWidget(label);
36 |
37 | comboBox_ = new QComboBox{this};
38 | comboBox_->setEditable(true);
39 | comboBox_->setMinimumWidth(200);
40 | layout->addWidget(comboBox_);
41 |
42 | populateComboBox();
43 |
44 | auto buttonBox = new QDialogButtonBox{QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this};
45 | connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
46 | connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
47 | layout->addWidget(buttonBox);
48 |
49 | setWindowTitle("Procedure");
50 | }
51 |
52 | std::string StoredProcedureDialog::getProcedure() const
53 | {
54 | return comboBox_->currentText().toStdString();
55 | }
56 |
57 | void StoredProcedureDialog::populateComboBox()
58 | {
59 | // display all names in current directory with extension of .psp (pdCalc stored procedure)
60 | QDir dir{"."};
61 | dir.setFilter(QDir::Files);
62 | QStringList lst;
63 | lst << "*.psp";
64 | dir.setNameFilters(lst);
65 |
66 | comboBox_->addItems( dir.entryList() );
67 |
68 | return;
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/pdCalc/src/ui/gui/StoredProcedureDialog.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef STORED_PROCEDURE_DIALOG_H
20 | #define STORED_PROCEDURE_DIALOG_H
21 |
22 | #include
23 | #include
24 |
25 | class QComboBox;
26 |
27 | namespace pdCalc {
28 |
29 | class StoredProcedureDialog : public QDialog
30 | {
31 | Q_OBJECT
32 | public:
33 | explicit StoredProcedureDialog(QWidget* parent = nullptr);
34 | std::string getProcedure() const;
35 |
36 | private:
37 | void populateComboBox();
38 |
39 | QComboBox* comboBox_;
40 | };
41 |
42 | }
43 | #endif
44 |
--------------------------------------------------------------------------------
/pdCalc/src/ui/gui/gui.pro:
--------------------------------------------------------------------------------
1 | HOME = ../../..
2 | include ($$HOME/common.pri)
3 | TEMPLATE = lib
4 | TARGET = pdCalcGui
5 | DEPENDPATH += .
6 | INCLUDEPATH += . $$HOME/src
7 | unix:DESTDIR = $$HOME/lib
8 | win32:DESTDIR = $$HOME/bin
9 |
10 | QT += widgets
11 |
12 | # Input
13 | HEADERS += MainWindow.h \
14 | Display.h \
15 | LookAndFeel.h \
16 | InputWidget.h \
17 | CommandButton.h \
18 | StoredProcedureDialog.h \
19 | GuiModel.h
20 |
21 | SOURCES += MainWindow.cpp \
22 | Display.cpp \
23 | LookAndFeel.cpp \
24 | InputWidget.cpp \
25 | CommandButton.cpp \
26 | StoredProcedureDialog.cpp \
27 | GuiModel.cpp
28 |
29 | win32:LIBS += -L$$HOME/bin -lpdCalcUtilities1 -lpdCalcBackend1
30 |
--------------------------------------------------------------------------------
/pdCalc/src/utilities/Exception.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef EXCEPTION_H
20 | #define EXCEPTION_H
21 |
22 | // Simple exception class to be used throughout PdCalc. It can be instantiated with a message,
23 | // and that message can be returned.
24 |
25 | #include
26 |
27 | namespace pdCalc {
28 |
29 | class Exception
30 | {
31 | public:
32 | explicit Exception(const std::string& msg) : msg_(msg) { }
33 | const std::string& what() const { return msg_; }
34 |
35 | private:
36 | std::string msg_;
37 | };
38 |
39 | }
40 |
41 | #endif
42 |
--------------------------------------------------------------------------------
/pdCalc/src/utilities/Observer.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "Observer.h"
20 | #include "Publisher.h"
21 |
22 | using std::shared_ptr;
23 | #include
24 |
25 | namespace pdCalc {
26 |
27 | Observer::Observer(const std::string& name)
28 | : observerName_{name}
29 | { }
30 |
31 | Observer::~Observer()
32 | {
33 |
34 | }
35 |
36 | void Observer::notify(std::shared_ptr d)
37 | {
38 | notifyImpl(d);
39 | return;
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/pdCalc/src/utilities/Observer.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef OBSERVER_H
20 | #define OBSERVER_H
21 |
22 | // The Observer class serves as the base class for all observer objects. The Observer class
23 | // is a mediator between the Publisher and the actual class that performs the observation.
24 | // A concrete observer should inherit from observer and contain a pointer to the actual observing
25 | // object. This decouples the observing object from knowing about publishers. Note that publishers
26 | // call Observer's notify, which must be implemented in the concrete observer to respond to event
27 | // notifications.
28 |
29 | // Note that the semantics of Publisher to to own the Observer uniquely (enforced by std::unique_ptr)
30 |
31 | #include
32 | #include
33 |
34 | namespace pdCalc {
35 |
36 | class EventData;
37 |
38 | class Observer
39 | {
40 | public:
41 | explicit Observer(const std::string& name);
42 | virtual ~Observer();
43 |
44 | void notify(std::shared_ptr);
45 |
46 | const std::string name() const { return observerName_; }
47 |
48 | private:
49 | virtual void notifyImpl(std::shared_ptr) = 0;
50 |
51 | std::string observerName_;
52 | };
53 |
54 | }
55 |
56 | #endif
57 |
--------------------------------------------------------------------------------
/pdCalc/src/utilities/Publisher.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "Publisher.h"
20 | #include "Observer.h"
21 | #include "Exception.h"
22 |
23 | #include
24 | #include
25 | #include
26 |
27 | using std::string;
28 | using std::vector;
29 | using std::set;
30 | using std::ostringstream;
31 | using std::unique_ptr;
32 | using std::shared_ptr;
33 |
34 | namespace pdCalc {
35 |
36 | class Publisher::PublisherImpl
37 | {
38 | using ObserversList = std::unordered_map>;
39 | using Events = std::unordered_map;
40 |
41 | public:
42 | PublisherImpl();
43 | ~PublisherImpl();
44 |
45 | void attach(const string& eventName, unique_ptr observer);
46 | unique_ptr detach(const string& eventName, const string& observer);
47 | void notify(const string& eventName, shared_ptr d) const;
48 | void registerEvent(const string& eventName);
49 | void registerEvents(const vector& eventNames);
50 | set listEvents() const;
51 | set listEventObservers(const string& eventName) const;
52 |
53 | Events::const_iterator findCheckedEvent(const string& eventName) const;
54 | Events::iterator findCheckedEvent(const string& eventName);
55 |
56 | private:
57 | Events events_;
58 | };
59 |
60 | Publisher::PublisherImpl::PublisherImpl()
61 | { }
62 |
63 | Publisher::PublisherImpl::~PublisherImpl()
64 | {
65 |
66 | }
67 |
68 | Publisher::PublisherImpl::Events::const_iterator Publisher::PublisherImpl::findCheckedEvent(const string& eventName) const
69 | {
70 | auto ev = events_.find(eventName);
71 | if( ev == events_.end() )
72 | {
73 | ostringstream oss;
74 | oss << "Publisher does not support event '" << eventName << "'";
75 | throw Exception{ oss.str() };
76 | }
77 |
78 | return ev;
79 | }
80 |
81 | Publisher::PublisherImpl::Events::iterator Publisher::PublisherImpl::findCheckedEvent(const string &eventName)
82 | {
83 | auto ev = events_.find(eventName);
84 | if( ev == events_.end() )
85 | {
86 | ostringstream oss;
87 | oss << "Publisher does not support event '" << eventName << "'";
88 | throw Exception( oss.str() );
89 | }
90 |
91 | return ev;
92 | }
93 |
94 | void Publisher::PublisherImpl::attach(const string& eventName, unique_ptr observer)
95 | {
96 | auto ev = findCheckedEvent(eventName);
97 | auto& obsList = ev->second;
98 |
99 | auto obs = obsList.find(observer->name());
100 | if( obs != obsList.end() )
101 | throw Exception("Observer already attached to publisher");
102 |
103 | obsList.insert( std::make_pair(observer->name(), std::move(observer)) );
104 |
105 | return;
106 | }
107 |
108 | unique_ptr Publisher::PublisherImpl::detach(const string& eventName, const string& observer)
109 | {
110 | auto ev = findCheckedEvent(eventName);
111 | auto& obsList = ev->second;
112 |
113 | auto obs = obsList.find(observer);
114 | if( obs == obsList.end() )
115 | throw Exception("Cannot detach observer because observer not found");
116 |
117 | auto tmp = std::move(obs->second);
118 | obsList.erase(obs);
119 |
120 | return tmp;
121 | }
122 |
123 | void Publisher::PublisherImpl::notify(const string& eventName, shared_ptr d) const
124 | {
125 | auto ev = findCheckedEvent(eventName);
126 | const auto& obsList = ev->second;
127 |
128 | for(const auto& obs : obsList)
129 | obs.second->notify(d);
130 |
131 | return;
132 | }
133 |
134 | void Publisher::PublisherImpl::registerEvent(const string& eventName)
135 | {
136 | auto i = events_.find(eventName);
137 | if( i != events_.end() )
138 | throw Exception{"Event already registered"};
139 |
140 | events_[eventName] = ObserversList{};
141 |
142 | return;
143 | }
144 |
145 | void Publisher::PublisherImpl::registerEvents(const vector& eventNames)
146 | {
147 | for(auto i : eventNames)
148 | registerEvent(i);
149 |
150 | return;
151 | }
152 |
153 | set Publisher::PublisherImpl::listEvents() const
154 | {
155 | set tmp;
156 | for(const auto& i : events_)
157 | tmp.insert(i.first);
158 |
159 |
160 | return tmp;
161 | }
162 |
163 | set Publisher::PublisherImpl::listEventObservers(const string& eventName) const
164 | {
165 | auto ev = findCheckedEvent(eventName);
166 |
167 | set tmp;
168 | for(const auto& kvp : ev->second)
169 | tmp.insert(kvp.first);
170 |
171 | return tmp;
172 | }
173 |
174 | Publisher::Publisher()
175 | {
176 | publisherImpl_ = std::make_unique();
177 | }
178 |
179 | Publisher::~Publisher()
180 | {
181 | // std::unique_ptr requires a definition of the destructor instead
182 | // of using the default because the destructor must appear in a scope
183 | // in which the complete definition of the template argument for
184 | // std::unique_ptr is known
185 | }
186 |
187 | void Publisher::attach(const string& eventName, unique_ptr observer)
188 | {
189 | publisherImpl_->attach(eventName, std::move(observer));
190 |
191 | return;
192 | }
193 |
194 | unique_ptr Publisher::detach(const string& eventName, const string& observer)
195 | {
196 | return publisherImpl_->detach(eventName, observer);
197 | }
198 |
199 | void Publisher::raise(const string& eventName, std::shared_ptr d) const
200 | {
201 | publisherImpl_->notify(eventName, d);
202 | return;
203 | }
204 |
205 | void Publisher::registerEvent(const string& eventName)
206 | {
207 | publisherImpl_->registerEvent(eventName);
208 | return;
209 | }
210 |
211 | void Publisher::registerEvents(const vector& eventNames)
212 | {
213 | publisherImpl_->registerEvents(eventNames);
214 | return;
215 | }
216 |
217 | set Publisher::listEvents() const
218 | {
219 | return publisherImpl_->listEvents();
220 | }
221 |
222 | set Publisher::listEventObservers(const string& eventName) const
223 | {
224 | return publisherImpl_->listEventObservers(eventName);
225 | }
226 |
227 | EventData::~EventData()
228 | {
229 |
230 | }
231 |
232 | }
233 |
234 |
235 |
--------------------------------------------------------------------------------
/pdCalc/src/utilities/Publisher.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef PUBLISHER_H
20 | #define PUBLISHER_H
21 |
22 | // The Publisher class is a class capable of receiving observers. Note that it is assumed
23 | // that a real publisher may publish multiple separate events. These are stored by string
24 | // name in a table. Since each event may have multiple observers, the table stores
25 | // a collection of observers.
26 |
27 | // Important: Publishers own the memory for their observers (enforced by std::unique_ptr)
28 |
29 | #include
30 | #include
31 | #include
32 | #include
33 |
34 | namespace pdCalc {
35 |
36 | class Observer;
37 |
38 | class EventData
39 | {
40 | public:
41 | virtual ~EventData();
42 | };
43 |
44 | class Publisher
45 | {
46 | class PublisherImpl;
47 | public:
48 | Publisher();
49 |
50 | void attach(const std::string& eventName, std::unique_ptr observer);
51 | std::unique_ptr detach(const std::string& eventName, const std::string& observerName);
52 |
53 | std::set listEvents() const;
54 | std::set listEventObservers(const std::string& eventName) const;
55 |
56 | protected:
57 | ~Publisher();
58 |
59 | void raise(const std::string& eventName, std::shared_ptr) const;
60 |
61 | void registerEvent(const std::string& eventName);
62 | void registerEvents(const std::vector& eventNames);
63 |
64 | private:
65 | std::unique_ptr publisherImpl_;
66 | };
67 |
68 | }
69 |
70 | #endif
71 |
--------------------------------------------------------------------------------
/pdCalc/src/utilities/Tokenizer.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "Tokenizer.h"
20 | #include
21 | #include
22 | #include
23 |
24 | using std::string;
25 | using std::istringstream;
26 | using std::istream_iterator;
27 |
28 | namespace pdCalc {
29 |
30 | Tokenizer::Tokenizer(const string& s)
31 | {
32 | istringstream iss{s};
33 |
34 | tokenize(iss);
35 | }
36 |
37 | Tokenizer::Tokenizer(std::istream& is)
38 | {
39 | tokenize(is);
40 | }
41 |
42 |
43 | Tokenizer::~Tokenizer()
44 | { }
45 |
46 | void Tokenizer::tokenize(std::istream& is)
47 | {
48 | tokens_.assign( istream_iterator{is}, istream_iterator{});
49 |
50 | for(auto& i : tokens_)
51 | std::transform(i.begin(), i.end(), i.begin(), ::tolower);
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/pdCalc/src/utilities/Tokenizer.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef TOKENIZER_H
20 | #define TOKENIZER_H
21 |
22 | #include
23 | #include
24 | #include
25 |
26 | namespace pdCalc {
27 |
28 | class Tokenizer
29 | {
30 | public:
31 | using Token = std::string;
32 | using Tokens = std::vector;
33 | using const_iterator = Tokens::const_iterator;
34 |
35 | explicit Tokenizer(const std::string&);
36 | explicit Tokenizer(std::istream&);
37 | ~Tokenizer();
38 |
39 | size_t nTokens() const { return tokens_.size(); }
40 |
41 | const_iterator begin() const { return tokens_.begin(); }
42 | const_iterator end() const { return tokens_.end(); }
43 |
44 | const Token& operator[](size_t i) const { return tokens_[i]; }
45 |
46 | private:
47 | void tokenize(std::istream&);
48 |
49 | Tokenizer() = delete;
50 | Tokenizer(const Tokenizer&) = delete;
51 | Tokenizer(Tokenizer&&) = delete;
52 | Tokenizer& operator=(const Tokenizer&) = delete;
53 | Tokenizer& operator=(Tokenizer&&) = delete;
54 |
55 | Tokens tokens_;
56 | };
57 |
58 | }
59 |
60 | #endif
61 |
--------------------------------------------------------------------------------
/pdCalc/src/utilities/UserInterface.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "UserInterface.h"
20 | const std::string pdCalc::UserInterface::CommandEntered = "CommandIssued";
21 |
--------------------------------------------------------------------------------
/pdCalc/src/utilities/UserInterface.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #ifndef USER_INTERFACE_H
20 | #define USER_INTERFACE_H
21 |
22 | #include
23 | #include "Publisher.h"
24 |
25 | namespace pdCalc {
26 |
27 | class CommandData : public EventData
28 | {
29 | public:
30 | CommandData(const std::string& s) : command_(s) { }
31 | const std::string& command() const { return command_; }
32 |
33 | private:
34 | std::string command_;
35 | };
36 |
37 | class UserInterface : protected Publisher
38 | {
39 | public:
40 | UserInterface() { registerEvent(CommandEntered); }
41 | virtual ~UserInterface() { }
42 |
43 | // post a message to the user
44 | virtual void postMessage(const std::string& m) = 0;
45 |
46 | // notifies the interface that the stack has changed
47 | virtual void stackChanged() = 0;
48 |
49 | using Publisher::attach;
50 | using Publisher::detach;
51 |
52 | // defines the event this publisher can raise
53 | // note that the string is defined in main.cpp of the application since
54 | // class UserInterface has no implementation file (in test driver for same
55 | // reason)
56 | static const std::string CommandEntered;
57 | };
58 |
59 | }
60 | #endif
61 |
--------------------------------------------------------------------------------
/pdCalc/src/utilities/utilities.pro:
--------------------------------------------------------------------------------
1 | HOME = ../..
2 | include ($$HOME/common.pri)
3 | TEMPLATE = lib
4 | TARGET = pdCalcUtilities
5 | DEPENDPATH += .
6 | INCLUDEPATH += . $$HOME/src
7 | unix:DESTDIR = $$HOME/lib
8 | win32:DESTDIR = $$HOME/bin
9 |
10 | DEFINES += BUILDING_UTILITIES
11 |
12 | # Input
13 | HEADERS += Exception.h \
14 | Observer.h \
15 | Publisher.h \
16 | Tokenizer.h \
17 | UserInterface.h
18 |
19 | SOURCES += Observer.cpp \
20 | Publisher.cpp \
21 | Tokenizer.cpp \
22 | UserInterface.cpp
23 |
24 | OTHER_FILES += \
25 | Publisher.o \
26 | Observer.o \
27 | Makefile
28 |
--------------------------------------------------------------------------------
/pdCalc/test/backendTest/CommandDispatcherTest.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Adam B. Singer
2 | // Contact: PracticalDesignBook@gmail.com
3 | //
4 | // This file is part of pdCalc.
5 | //
6 | // pdCalc is free software; you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation; either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // pdCalc is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with pdCalc; if not, see .
18 |
19 | #include "CommandDispatcherTest.h"
20 | #include "src/utilities/UserInterface.h"
21 | #include "src/backend/CoreCommands.h"
22 | #include "src/backend/CommandDispatcher.h"
23 | #include "src/backend/CommandRepository.h"
24 | #include "src/backend/Stack.h"
25 |
26 | #include
27 | #include