Function? Sure. Aside: I’ll avoid the term ‘clamp’ in the function which has no meaning for Tinderbox users and would only confuse.
So here is a specimen function (for those not used to Discourse forum software, the forum default syntax colouring below is not marking Tinderbox syntax but gets close to it):
function fXReset(iXpos,iWidth,iMin,iMax,iShim,iReport){
// inputs arrive as strings so coerce to correct type
// passing inputs to typed variables confirms data type
// *ALL* inputs must be supplied
// iXpos is source note $Xpos
var:number vX = iXpos;
// iWidth is source notes $Width
var:number vW = iWidth;
// iMin is left-most allowed X-axis value
var:number vMin = iMin;
// iMax is right-most allowed X-axis value
var:number vMax = iMax;
// iShim is buffer so moved note is visibly inside limit
var:number vShim = iShim;
// iReport toggle postion report in $Subtitle, for testing
var:boolean vReport = vReport;
if (vX<=vMin | (vX+vW)>=vMax ) {
if(vX<=vMin){
vX=(vMin+vShim);
};
// as $Xpos is note top-left corner, postive axis
// value must allow for $Width to remain fully in bounds
if((vX+vW)>=vMax){
vX=((vMax-vShim)-vW);
};
};
// report current $Xpos
if(vReport){
$Subtitle = "X co-ord: "+vX.precision(2);
} else {
$Subtitle =; // reset $Subtitle to defualt, i.e. no text
}
// return new $Xpos
return vX;
}
The function is invoked with an action like this:
$Xpos = fXReset($Xpos,$Width,-10,10,0.1,true);
We can also call the function via an agent. But, noting that $Xpos is an intrinsic attribute we must use $Xpos(original)
otherwise we set the $Xpos
of the alias in the agent and not the alias’ original note.
$Xpos(original) = fXReset($Xpos(original),$Width,-10,10,0.1,true);
Both methods work. In my very small test doc, calling from a rule resulted in faster update than an agent. As both methods work, there is no ‘correct’ method of calling the function.
Notes:
- Tinderbox functions fail if any defined terms are not passed from the calling action
- Currently function input arguments are all received as String-type data. This may change, but until then it is advisable to use typed variables (see var operator).
- I’m not a programmer so others may see a more efficient way of doing this, but the code is tested in v9.1.0)
- The ‘shim’ is just a visual artifice for the test so we can see the note and test boundary (simulated by the adornments).
- Adjustment is made for positive X because in order for the whole note to be inbounds, we need to allowed for the note icon width ($Xpos is the position of the top-left corner of the note). This may not be a necessary
- The function cares nothing about Y-axis position. If the user drags a note out of bounds at the same Y positions several times, the moved notes will stack. In the demo as the test notes are the same size, the oldest notes in such a stack will appear to vanish as they are hidden.
- Tinderbox has no user-available ‘collision-avoidance’ routine, before anyone asks.
- It is perfectly possible to track Y-axis position too. If needed, I’d suggest using discrete function so you don’t have a vast number of arguments. Anyway this is left as an exercise for those who need it.
- Another possibility is to set some marker (visible or just a general user attribute) that a note has passed out of bounds and been moved. But you will also need to consider how/when that flag is reset, if needs be.
- The function arguments could be passed as a list, but I don’t think it helps any. The individual arguments inputs still have to found and mapped to correct data type. In addition, unless a function is building the list, I think the apparent concision achieved just adds complexity and chance of error.
- Bear in mind that once function and calling code are written, you don’t need to touch it again. But clear layout of code and comments will help future self understand it weeks/months/years later. for instance, if type-support for arguments arrives, lots of the casting to typed variables can be removed.
- Not used here but possibly helpful when building is to use a logging function, e.g. to debug position & shimming. Using rules or agents, beware of logging that accretes input (i.e.
$Text += ...
) as this will add a lot of entries quickly (and keeps going when you step away to take a call or grab a drink!). In such circumstances consider using edicts, low priority agents or stamps for initial testing so the logging is actually useful.
- Although disabled by default, when using map-based behaviours like this, be aware of composites: how they work and how to disable remove them if they somehow get invoked.
- Beware issues of scale with processes like this. What works for a few test notes might not work so well with 100s of such notes. My suggestion, think defensive and assume there will be scale problems. You may either be happily surprised or at least not disappointed. Otherwise, as seen often in the past, the user ends up blaming the app for their own error and lack of foresight. The sort of thing we are doing here can be done, but I strongly doubt many of the processes used were designed for (fast-updating) interactive maps. So, don’t over-demand of the app.
I did note in an earlier post that @jxxmxxj is actually using the map X-axis as a timeline, in which case do look at Tinderbox’s timeline view. It might help, though I’ve insufficient use case detail to be able to say. Also, if using the above ideas be aware date arithmetic in action code has some idiosyncrasies > Again, Tinderbox’s action code is not [your favourite formal code language], so expect syntax to differ from your assumed norms rather than that action code should be like some unknown (to Tinderbox) other system…
I’ve updated my earlier TBX to use 3 pairs of notes, each based on a discrete prototype. Two prototype’s use a rule to call the function, and one is worked via and agent. This is simply to chow both approaches could be used.
I’ve run out of time to read a read-me, but the test part is seen below, in the first (left-most) tab which uses map view. The doc is saved with this tab selected (you may need to scroll the map a bit to see what you want:
The second (right-most) tab is set to a root-level outline view giving access to everything:
…and finally the test TBX: x-reset-test.tbx (120.4 KB)