If you use BricsCAD or AutoCAD in your organization, it is a good idea to put all of your customization in a work space of its own. When in a network it can be a bumpy road to achieve this remotely. This article describes techniques to achieve this.
A word about AutoCAD: It is assumed the procedure is similar but this article is focussed around BricsCAD. However only on minor details you may have to tweak some things.
On the net there are examples of unexpected challenges related to work-space actions and LISP. See for example this (dead link http://jprdintprev.autodesk.com/adn/servlet/devnote?siteID=4814862&id=5790155&preview=1&linkID=4900509), for an approach.
In the title the word “Network” is included because focus is on a work group. It does not mean you cannot use this article in a stand-alone situation. Here we go…
Table of Contents
Access Work Spaces
That one is easy, in the right bottom area you’ll find the current work space, right click it to select what you want.
Alternatives:
- Activate toolbar “Workspaces“
- Use command
WORKSPACE
What is a Work Space?
A work space is a customized user interface. More specific: toolbars, ribbons, palettes and QUAD-tabs. In fact, it is nothing more than that.
It is all about visual experience, all about CUI‘s, or customized user interfaces – the menu’s. Work spaces are defined in your default.cui – the main menu that comes with the program. Do a CUI
command, select tab “workspaces” and see what it contains.
Some Experiments
Experiment 1: I have a partial menu with a “my-workspace” pointer in it. I load it and “my-workspace” is added. Bummer, it does not work that way, default.cui does need an entry for “my-workspace“. How to get around that without manually editing default.cui?
Experiment 2: I have a partial menu prepared with a toolbar, looks good. I make a workspace with WORKSPACE SA
(Save As) “my-workspace“, make it active, do CUILOAD
and there is my toolbar. Looks good too! Bummer, all work spaces now show this toolbar.
Conclusion
Putting work spaces in default.cui, without any alternatives, is a debatable design choice. Command WORKSPACE
edits default.cui. That solves the problem in experiment 1.
Creating partial menu’s is preferred. However all toolbars should be hidden as default and only be shown – with command TOOLBAR
for example – after making the desired workspace active. And that solves problem 2.
And the pointer “my-workspace” in the partial menu? That remains a mystery! But with this information, it should be possible to automate some things. Let’s give it a try, from easy to complex, see where we end up with.
Planning Manipulating Work Spaces
Before jumping into solutions, let’s chop the problem into parts.
- There is no proper (LISP) API to list work spaces from the cui(x).
- We want to know if a work space exists.
- Based on the outcome we want to take appropriate action.
- If a work space does not exist, we want to make it.
- If we make a work space we need to choose an existing work space as a base.
It is tempting to hack a piece of code and get it working like in the link above – nothing wrong with that. With API shortcomings it is not a problem when a solution is a bit dirty, as long as it is reliable. What happens if we paste on the command line:
(setvar 'wscurrent "Undefined Work Space") |
Right, it causes an error and crashes the LISP routine. So it is useless to put such a statement in a “if” construction, we are back to nil. That is the reason the construction mentioned in the top of this post is interesting because it uses the error. But… It does not work in BricsCAD (actually, that is quite surprising because it does not happen often). It is a complex solution but in it’s base it is smart to use the error. By the way, we could probably use the *error* handler for this too. Abusive, never tried but probably possible and… we’re not going to do that. Time for an alternative that is based around this statement:
(vl-catch-all-apply 'setvar (list 'wscurrent "a workspace name")) |
This statement makes an existing work space “a workspace name” current. But it does not create “a workspace name” if it does not exists in default.cui. The error generated when work space does not exists can be processed with (vl-catch-all-error-p error-object)
. Time for some code.
A function ws-make
Function ws-make creates a new work space if it does not exist and sets it current (analogue to -layer command, hence “make“).
Syntax:
(ws-make <"work space to make"> <"base work space"> <T|nil>)
Argument 1: <“work space to make“> is obvious.
Argument 2: Choose an existing work space as template, i.e. “base work space“.
Argument 3: Overwrite an existing work space, i.e. T, or not, i.e. nil.
A program flow should start with an exception: Test if work space to make is the current work space without a request to overwrite. This is because all following code will change screens from work space to work space.
Every (setvar 'wscurrent "string")
statement should be limited because of screen changes – but switching is inevitable.
Here is a branching table:
ws-to-make |
ws-overwrite |
variant |
exists, current |
nil |
1 |
not exists |
T |
2 |
not exists |
nil |
3 |
exists, current |
T |
4 |
exists, not current |
T |
5 |
exists, not current |
nil |
6 |
The variants can be found as comments in the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | (defun ws-make (ws-to-make ws-base ws-overwrite / ws-to-make ws-base ws-overwrite ws-cur) (setq ws-cur (getvar 'wscurrent)) (if (and (= ws-overwrite nil) (= (strcase ws-to-make) (strcase ws-cur))) (princ (strcat"\nRequested work space " ws-to-make " was already defined and current.")) ; 1 !! (if (vl-catch-all-error-p (vl-catch-all-apply 'setvar (list 'wscurrent ws-base))) (princ (strcat "\nError: base work space " ws-base " does not exist. ")) (if (vl-catch-all-error-p (vl-catch-all-apply 'setvar (list 'wscurrent ws-to-make))) (progn (setvar 'wscurrent ws-base) (command "._workspace" "_sa" ws-to-make "._workspace" "_c" ws-to-make) (princ (strcat "\nWork space " ws-to-make " did not exist and is created. ")) ; 2 and 3 !! ) (progn (if ws-overwrite (progn (setvar 'wscurrent ws-base) (command "._workspace" "_d" ws-to-make "_y" "._workspace" "_sa" ws-to-make) (setvar 'wscurrent ws-to-make) (princ (strcat "\nRequested work space " ws-to-make " was already defined but is overwritten by a work space based on " ws-base " and is set current.")) ; 4 and 5 !! ) (princ (strcat"\nRequested work space " ws-to-make " was already defined and is set current.")) ; 6 !! ) ) ) ) ) (princ) ) |
Last words about ws-make
Function ws-make is a solution, period. But… It is a bit hackish and screams for a different approach. More on that later. For now, again, we have a solution that is clean when a work space is supposed to be current and actually is current (variant 1).
When starting a document or the program or simply on request, ws-make can help to create a user environment, we’re not finished yet.
About “More on that later”: parsing default.cui is the way to go, but that creates other challenges like editing a loaded menu, saving and reloading it. I’ll show you a piece of the default.cui pie:
<Workspace MenuBar="on" ScrollBars="ignore">
<Name>New name ws-to-make</Name>
<Description>Old description of ws-base</Description>
Time for Toolbars
The toolbars in your partial cui file are hidden and it is time to activate them. For simple things, good old unix style config files without the xml shizzle are preferred.
About the location of your config file, it is a bad habit to use hard locations. It is better to put them in SFSP and use (findfile “workspaces.cfg”) to locate them. If you have a department share and a user share you may want to put the user share above the department share in SFSP. This way a user is free to create a copy of workspaces.cfg with favorite settings.