How to set custom colors for Odoo 12 calendar view events? - odoo

There is a good tutorial on how to achieve this in Odoo-8 here:
Tutorial , but it doesn't work on Odoo-12.
Odoo natively allows you to set a field of your model as a basis for color differentiation in calendar view.
<calendar ... color="your_model_field">
The problem is that he will decide automagically what color to assign to every value.
I need to be able to decide what color mapping to use.
Doing some diving in the web module js files, more specifically on
web/static/src/js/views/calendar/calendar_renderer.js on line 266
I found a promising function which appears to be the one responsible for deciding which color to set.
getColor: function (key) {
if (!key) {
return;
}
if (this.color_map[key]) {
return this.color_map[key];
}
// check if the key is a css color
if (typeof key === 'string' && key.match(/^((#[A-F0-9]{3})|(#[A-F0-9]{6})|((hsl|rgb)a?\(\s*(?:(\s*\d{1,3}%?\s*),?){3}(\s*,[0-9.]{1,4})?\))|)$/i)) {
return this.color_map[key] = key;
}
var index = (((_.keys(this.color_map).length + 1) * 5) % 24) + 1;
this.color_map[key] = index;
return index;
},
This function is fed the value of your field (for every calendar event) and returns the color to be used "supposedly" as background for the calendar event square.
According to the second if statement, if you manage to instantiate the CalendarRenderer class with a color_map object which has the possible values of your field as keys and color codes as values you should be ok.
According the the third if statement, if the values of your field are strings with color codes (#FFF, rgb(x, y, z) , etc) they will be set in the color_map object and returned to be used as background colors.
The last part I guess is how odoo decides on a color when no mapping is provided.
I tried both approaches with the same efect:
Image displaying the calendar view
Namely, all the calendar events are rendered with the default color taken from the fullcalendar.css stylesheet (line 529), but the color reference displays correctly on the sidebar to the right.
I would appreciate any light shed on this matter, It has to be possible to make this work!.
Thanks.

Related

Custom CollapsingTopAppBar Jetpack Compose

The essence of the problem is that I want to write my own version of the AppBar that would include content as another Compose function. After looking at the source code of the current CollapsingTopAppBar implementation, I saw the following lines:
#Composable
private fun TwoRowsTopAppBar(
...
scrollBehavior: TopAppBarScrollBehavior?
) {
...
val pinnedHeightPx: Float = 64.dp
val maxHeightPx: Float = 152.dp
LocalDensity.current.run {
pinnedHeightPx = pinnedHeight.toPx()
maxHeightPx = maxHeight.toPx()
}
// Sets the app bar's height offset limit to hide just the bottom title area and keep top title
// visible when collapsed.
SideEffect {
if (scrollBehavior?.state?.heightOffsetLimit != pinnedHeightPx - maxHeightPx) {
scrollBehavior?.state?.heightOffsetLimit = pinnedHeightPx - maxHeightPx
}
}
...
Surface(...) {
Column {
TopAppBarLayout(
...
heightPx = pinnedHeightPx
...
)
TopAppBarLayout(
...
heightPx = maxHeightPx - pinnedHeightPx + (scrollBehavior?.state?.heightOffset
?: 0f),
...
)
}
}
}
As I understand it, scrollBehavior is used to handle the collapse and expansion behavior. In the current implementation, just constant values are put in heightOffsetLimit. And since I need my appbar implementation to be able to contain content of any size, I need to somehow know the size of this content in advance and put this value in heightOffsetLimit.
I have already written the code for my AppBar, so that it also contains content. But since I can't pass the height value of the content to scrollBehavior, the AppBar doesn't collapse to the end.
you need to calculate the height that the appbar will have before drawing it into the screen. I have followed this issue and solved my problem with the last solution. hope it helps:
Get height of element Jetpack Compose
use the content you can put (ex. an image or a huge text) as the MainContent
use your appbar as the DependentContent and use the size given in lambda to give the height to your appbar
finally set placeMainContent false as I believe you don't need to draw the image (or any other composable) directly in a box
and you will good to go

Photoshop CC eye dropper tool script

I have a batch action to place a pure white background behind an image. I want to be able to select the color from a fixed pixel position on each photo. When I record the eye dropper in actions it only records the color i picked, not the action of picking the color. I have looked into scripting and tried various solutions on the web.
This is the script I have tried:
var docRef = app.activeDocument;
var pixelLoc = [32,42];
var colorSamplerRef = docRef.colorSamplers.add(pixelLoc);
app.foregroundColor = colorSamplerRef.color;
It doesn't perform the action I need though. Which is select - > color range -> eye dropper tool on fixed position
To achieve this you can create a custom function which invokes the Color Range generated selection, (named selectColorRange in the example gist below).
The selectColorRange function utilizes new ActionDescripter() to configure the properties, which are akin to the settings options shown in the dialog box when you manually choose Select -> Color Range from the Menu bar. This function is invoked after adding the colorSampler at a given x/y coordinate as follows:
selectColorRange(sampledColor, 80); // <-- Specify the fuzziness as required.
Note how we pass in the previous sampledColor value, and a fuzziness value of 80, (which is the default value used in Photoshop).
Example gist:
var docRef = app.activeDocument; // Assumes a document is active.
// Remove any Color Samplers that may already exist.
docRef.colorSamplers.removeAll();
// deselct any selection that may already exist.
docRef.selection.deselect();
// Get color sample from a given x,y coordinate.
var pixelLoc = [32,42];
var colorSampleRef = docRef.colorSamplers.add(pixelLoc);
var sampledColor = colorSampleRef.color;
// Set the foreground color to the sampled color.
app.foregroundColor = sampledColor;
/**
* Invokes and configures `Select > Color Range` from menu bar.
* #param {Object} color - The sampled color object.
* #param {Number} [fuzziness=80] - The Fuziness value (between 0-200).
*/
function selectColorRange(color, fuzziness) {
fuzziness = (typeof fuzziness !== 'undefined') ? fuzziness : 80;
var d1 = new ActionDescriptor();
// Set the amount of Fuzziness.
d1.putInteger(charIDToTypeID('Fzns'), fuzziness);
// Set invert option to false.
d1.putBoolean(charIDToTypeID('Invr'), false);
d1.putInteger(stringIDToTypeID('colorModel'), 0);
// Set the lAB value for Minimum.
var d2 = new ActionDescriptor();
d2.putDouble(charIDToTypeID('Lmnc'), color.lab.l);
d2.putDouble(charIDToTypeID('A '), color.lab.a);
d2.putDouble(charIDToTypeID('B '), color.lab.b);
d1.putObject(charIDToTypeID('Mnm '), charIDToTypeID('LbCl'), d2);
// Set the lAB value for Maximum.
var d3 = new ActionDescriptor();
d3.putDouble(charIDToTypeID('Lmnc'), color.lab.l);
d3.putDouble(charIDToTypeID('A '), color.lab.a);
d3.putDouble(charIDToTypeID('B '), color.lab.b);
d1.putObject(charIDToTypeID('Mxm '), charIDToTypeID('LbCl'), d3);
// Run the Color Range command without showing dialog.
executeAction(charIDToTypeID('ClrR'), d1, DialogModes.NO);
}
// Invoke the function passing in the sample
// color and default fuzziness value.
selectColorRange(sampledColor, 80);
//docRef.selection.clear();
//docRef.selection.fill(app.foregroundColor);
// Remove the Color Sampler.
colorSampleRef.remove();
Additional notes:
Photoshop allows a maximum of four color samplers to be added. If the document already included four color samplers then we'd get an error when attempting to add another one. To avoid the potential of this happening we invoke docRef.colorSamplers.removeAll(); to remove them all first.
Also, to ensure the resultant selection (i.e. the selection created after invoking the selectColorRange function), is not affected by any existing selection(s) we deselect them all first by invoking docRef.selection.deselect();
Finally, the color sampler that we initially added is removed by calling colorSampleRef.remove();
I'm unsure from your question what you intend to to with the selection once it's been created. As an example;
Lets say you wanted to clear the contents of the selection then you'd invoke docRef.selection.clear();.
If you wanted to fill the resultant selection with the previously sampled color then call docRef.selection.fill(app.foregroundColor);

constrain proportions while resizing images

I implemented drag and drop of images and now i want to constrain proportions of images while resizing.
/**
* Variable: constrainChildrenOnResize
*
* Specifies if children should be constrained according to the <constrainChildren>
* switch if cells are resized (including via <foldCells>). Default is false for
* backwards compatiblity.
*/
mxGraph.prototype.constrainChildrenOnResize = false;
i set this to true but its not working :s
What API/property i need for this functionality..
constrainChildrenOnResize is responsible for positioning and size of the children of resized cell. It means that children should keep their position relatively to the parent-cell.
In your case I would suggest to extend mxVertexHandler using union method. In this example you can see how to implement min-width/min-height restrictions. Using this example you are able to write your own rules for constrain.
Here is my simple solution:
var vertexHandlerUnion = mxVertexHandler.prototype.union;
mxVertexHandler.prototype.union = function (bounds) {
var result = vertexHandlerUnion.apply(this, arguments);
var coff = bounds.width / bounds.height
result.width = result.height * coff;
return result;
};
So this function is called every time you move mouse during dragging the resizer.
bounds - object, always same and represent old geometry of the cell (before resizing)
result - object, represents new values, which are going to be applied. Between this line ad return statement you can place any code you need to modify result.
In my simple example I just get the initial relation between width and height of the cell (coff) and then set new width by multiplying coff and new height. It will work if you drag corner or top/bottom. In real project this logic should be slightly extended, or you should make visible only corner handlers.
By the way, this code will work for all resizable cells on your graph. If you want to apply it only to images or some other kind of cells - you can put condition and check the cell type before recalculating. You can get current cell or its state via this.state.cell or this.state inside of union function.
For example only for vertecies:
... ...
var result = vertexHandlerUnion.apply(this, arguments);
if (this.state.cell.isVertex()) {
//calculations here
}
return result;

Dojo:how to find if the widget has focus in dojo

how do I find out if my custom widget has focus in Dojo?
i have dojo editor i wnat to know if the editor has already focus or not?
you can use the module dijit/focus to find out the focus
FROM DOJO DOCS
Tracking active widgets
At any point in time there is a set of (for lack of a better word)
“active” or “focused” widgets, meaning the currently focused widget
and that widget’s ancestors. “Ancestor” can mean either DOM ancestor
(ex: TextBox –> Form), or a logical parent-child relationship (ex:
TooltipDialog –> DropDownButton).
For example, if focus is on a TextBox inside a TabContainer inside a
TooltipDialog triggered by a DropDownButton, the stack would be
TextBox –> ContentPane –> TabContainer –> TooltipDialog –>
DropDownButton.
The activeStack[] parameter indicates this set of widgets, and an app
can monitor changes to activeStack[] by:
require([ "dijit/focus" ], function(focusUtil){
focusUtil.watch("activeStack", function(name, oldValue, newValue){
console.log("Focused widget + ancestors: ", newValue.join(", "));
});
});
the question in title has a different answer than the one in the descriptions.
there are two ways achieving the question in the title, by using dojo's focusUtil ("dijit/focus"). both ways give you something that you could find the widget using it and the dijit's registry ("dijit/registry").
focusUtil.curNode: gives you the DOM Node that currently has the focus. the function below, you could get the widget reference.
function getWidgetByNode(node){
var result;
while (!result && node){
result = registry.byNode(node);
if (node.parentElement)
node = node.parentElement;
else
node = null;
}
return result;
}
var focusedWidget = getWidgetByNode(focusUtil.curNode)
focusUtil.activeStack: gives you an array of the widgets (parent to child) that has the focus. so the last item in the array is the direct widget which has the focus. index values are widget ids, so you should get the widget by the following code
var focusedWidgetId = focusUtil.activeStack[focusUtil.activeStack.length-1];
var focusedWidget = registry.byId(focusedWidgetId);
now if you want to know if the currently focused widget is some specific one, it depends on what you have in hands from that specific widget:
widget itself: like the return values of above samples. now you have to compare if these are the same thing. you can not compare two widget objects using the == operator. you could compare their ids like this:
myWidget.id == focusedWidget.id
widget's id: this way you just easily get the id of the current node from focusUtil and compare it with the id you have liek this:
myWidgetId == focusedWidgetId
references:
http://dojotoolkit.org/reference-guide/1.9/dijit/focus.html
http://dojotoolkit.org/reference-guide/1.9/dijit/registry.html
require([ "dijit/focus" ], function(focusUtil){
var activeElement = focusUtil.curNode; // returns null if there is no focused element
});
check blow url here you can see some examples
http://dojotoolkit.org/reference-guide/1.8/dijit/focus.html#dijit-focus
a) For dojo 1.6: call dijit.getFocus(). This will return an object containing the currently focused dom node, among other things (selected text, etc.). To get the corresponding widget, simply do:
var activeElement = dijit.getEnclosingWidget(dijit.getFocus().node);
This is the full reference for dijit.getFocus(), from the source code:
// summary:
// Called as getFocus(), this returns an Object showing the current focus
// and selected text.
//
// Called as getFocus(widget), where widget is a (widget representing) a button
// that was just pressed, it returns where focus was before that button
// was pressed. (Pressing the button may have either shifted focus to the button,
// or removed focus altogether.) In this case the selected text is not returned,
// since it can't be accurately determined.
//
// menu: dijit._Widget or {domNode: DomNode} structure
// The button that was just pressed. If focus has disappeared or moved
// to this button, returns the previous focus. In this case the bookmark
// information is already lost, and null is returned.
//
// openedForWindow:
// iframe in which menu was opened
//
// returns:
// A handle to restore focus/selection, to be passed to `dijit.focus`.
b) For dojo 1.7 and up, use dijit/focus:
require([ "dijit/focus" ], function(focusUtil) {
var activeElement = focusUtil.curNode; // returns null if there is no focused element
});

dojox.drawing.Drawing - custom tool to create rectangle with rounded corners

I'm working with dojox.drawing.Drawing to create a simple diagramming tool. I have created a custom tool to draw rounded rectangle by extending dojox.drawing.tools.Rect as shown below -
dojo.provide("dojox.drawing.tools.custom.RoundedRect");
dojo.require("dojox.drawing.tools.Rect");
dojox.drawing.tools.custom.RoundedRect = dojox.drawing.util.oo.declare(
dojox.drawing.tools.Rect,
function(options){
},
{
customType:"roundedrect"
}
);
dojox.drawing.tools.custom.RoundedRect.setup = {
name:"dojox.drawing.tools.custom.RoundedRect",
tooltip:"Rounded Rect",
iconClass:"iconRounded"
};
dojox.drawing.register(dojox.drawing.tools.custom.RoundedRect.setup, "tool");
I was able to add my tool to the toolbar and use it to draw a rectagle on canvas. Now, I would like to customize the rectangle created by my custom tool to have rounded corners, but I'm not able to figure out how.
I have checked the source of dojox.drawing.tools.Rect class as well as it's parent dojox.drawing.stencil.Rect class and I can see the actual rectangle being created in dojox.drawing.stencil.Rect as follows -
_create: function(/*String*/shp, /*StencilData*/d, /*Object*/sty){
// summary:
// Creates a dojox.gfx.shape based on passed arguments.
// Can be called many times by implementation to create
// multiple shapes in one stencil.
//
//console.log("render rect", d)
//console.log("rect sty:", sty)
this.remove(this[shp]);
this[shp] = this.container.createRect(d)
.setStroke(sty)
.setFill(sty.fill);
this._setNodeAtts(this[shp]);
}
In dojox.gfx, rounded corners can be added to a a rectangle by setting r property.
With this context, could anybody please provide answers to my following questions?
What's the mechanism in dojox.drawing to customize the appearance of rectangle to have
rounded corners?
In the code snippet above, StencilData is passed to createRect call. What's the mechanism to customize this data? Can the r property of a rectangle that governs rounded corners be set in this data?
Adding rounded rectangles programmatically is easy. In the tests folder you'll find test_shadows.html which has a line that adds a rectangle with rounded corners:
myDrawing.addStencil("rect", {data:{x:50, y:175, width:100, height:50, r:10}});
You create a data object with x,y,width,height, and a value for r (otherwise it defaults to 0).
If you wanted to do it by extending rect, the easiest way to do it would just be to set the value in the constructor function (data.r=10, for example), or you could create a pointsToData function to override Rect's version. Either you would have set the value for this.data.r, or the default:
pointsToData: function(/*Array*/p){
// summary:
// Converts points to data
p = p || this.points;
var s = p[0];
var e = p[2];
this.data = {
x: s.x,
y: s.y,
width: e.x-s.x,
height: e.y-s.y,
r:this.data.r || 10
};
return this.data;
},
In that example I give r the value 10 as the default, instead of 0 as it was before. This works because every time stencil goes to draw your rect, it converts canvas x,y points (all stencils remember their points) to data (which gfx uses to draw). In other words this function will always be called before rect renders.