My objective is to build a Dojo widget that embeds some graphic information, for example an Analogue Gauge, along with some other stuff.
I have managed to build a widget and initialise the Analogue widget with code such as:
gauge = new dojox.widget.AnalogGauge({
id: "defaultGauge",
width: 300,
height: 200,
cx: 150,
cy: 175,
radius: 125,
Now I've generalised this so that the width, height, cx, cy and radius can be calculated if I know the dimensions in which the widget will be rendered. Say for example, it's going to be in the "top" region of a Border Layout of height 150px, then I can compute suitable values.
The question: how do I determine the available space for my widget to work in? Is there some API by which I can obtain this information from the Layout or Content Pane?
It seems that the widget can provide a
resize(dimensions)
method, which is called both when the widget is first displayed and also when it is resized. The argument being an object holding the width and height of the display area.
Hence if the
gauge = new dojox.widget.AnalogGauge({
code is moved into the resize method we can provide suitable size information to the gauge constructor. I have yet to understand how to deal with subsequent resize() requests.
Related
I am using iOS Charts (Daniel Gindi) to generate graphs in an iOS app and I want to be able to generate a PDF report with those graphs included in the body of the report. Can anyone explain how to go about doing this. Ideally I don't want to generate an image from the UIView that shows in the app because the size/resolution would not be suitable for the PDF document.
As I understand it there are a few options:
use the graphics context for the pdf document to draw the graph on - it's not clear whether this would be possible when using the Charts library
use a UIView somehow to generate the graph and generate a PDF image data from that, embed this image into the pdf report
It seems like option 1 is probably the preferred way to get best resolution/control - somewhat speculative - doing it this way means you should be able to specify the exact position and size and get the correct font sizes, line thicknesses, etc..
Using option 2 means you have to figure out the scaling between a UIView and the PDF page view and I am not sure how these would map to each other.
Can anyone provide any suggestions on the following:
Is it possible to use Charts to generate graphs in a PDF document, and if so how?
If not what other options are there, short of writing custom drawing code.
OK so here is what I have done
Option 1: Using a UIView.layer to render on the PDF CGContect
func drawLineGraph(x: CGFloat, y: CGFloat)->CGRect{
let width = (pageSize.width - 2*kBorderInset - 2*kMarginInset)/2.0 - 50.0
let renderingRect = CGRect(x: x, y: y + 50.0, width: width, height: 150.0)
// Create a view for the Graph
let graphController = LineChartController(rect: renderingRect, building: self.building)
if let currentContext = UIGraphicsGetCurrentContext() {
let frame = graphController.chartView.frame
currentContext.saveGState()
currentContext.translateBy(x:frame.origin.x, y:frame.origin.y);
graphController.chartView.layer.render(in: currentContext)
currentContext.restoreGState()
}
return renderingRect
}
The graphController is just an object that has essentially the same function as the usual parent ViewController that would contain the graph. Sets the graph parameters and data.
Once that has been done the function below is called to render on the PDF page context.
A bit of translation required to put the graphs in the correct position.
Option 2: Drawing on the PDF Page CGContect
And the solution is...ta da...
func drawBarGraph(x: CGFloat, y: CGFloat)->CGRect{
let width = (pageSize.width - 2*kBorderInset - 2*kMarginInset)/2.0 - 50.0
let renderingRect = CGRect(x: x + width + 50, y: y + 50.0, width: width, height: 150.0)
// Create a view for the Graph
let graphController = BarChartController(rect: renderingRect, building: self.building)
if let currentContext = UIGraphicsGetCurrentContext() {
let frame = graphController.chartView.frame
currentContext.saveGState()
currentContext.translateBy(x:frame.origin.x, y:frame.origin.y)
//graphController.chartView.layer.render(in: currentContext)
graphController.chartView.draw(frame)
currentContext.restoreGState()
}
return renderingRect
}
Since the current context is set to the PDF page's context just call the charts draw() function directly passing the frame rectangle.
What have I missed here, can it be this easy ?
You can find a copy of the generated PDF here as well as sample code.
So I'm aware you can use a function to compute a css property in Cytoscape.js e.g.
cytoscape.stylesheet()
.selector('node')
.css({
'width': function(ele) {
return 12;
})
I'm also aware of the special value 'label' that can be the value of the property e.g.
cytoscape.stylesheet()
.selector('node')
.css({
'width': 'label'
})
What I'm wondering is is there any particular property I could use to scale the label by some factor, e.g. what I want is something like
cytoscape.stylesheet()
.selector('node')
.css({
'width': function(ele) {
return labelWidth * 1.5; //Where to get labelWidth from
})
Specially I want the ability to be able to calculate the height and width of an ellipse so that the label is completely contained within the ellipse (which can be computed using some math e.g. Ellipse bounding a rectangle).
But I haven't been able to find a way to get the labelWidth. I did manage to do it using rscratch but only if the node actually got rendered twice (e.g. multiple .selectors), any proper way to get the label width and height from a given element (or at least a way to calculate how it'll be rendered?).
If you want to do more sophisticated sizing, your calculations are going to have to be more sophisticated.
Options :
(1) Calculate the dimensions of the text yourself using a div.
(2) Use the auto sizing, and then adjust the size based on the current size.
(1) is cleaner than (2).
It doesn't make sense for Cytoscape.js to expose rendered calculated values for you in the stylesheet. Those values are calculated from the stylesheet, creating a dependency cycle.
If you just want the label inside your node, you could just set the padding attribute to make more space around the text.
I was created a new project using flash cc html5 canvas and created a movieclip with 200px width and 200px height. I can able to get the properties using this.mc.nominalBounds;. And I tried this.mc.getBounds ();
But it returns null. setBounds also not seems to work.
The setBounds method is for putting a custom bounds on something, or defining it when it can not be determined (like using the Graphics classes). Fortunately, all symbols from Flash CC come with nominalBounds, which is the combined, untransformed size of the symbol.
Using that, you can set the scaleX and scaleY properties to size up and down your content. If you want it to be a specific width, just use the nominalBounds to determine a new scale.
For example, if the clip is 200x200, and you want it to be 400x400, then:
var scale = newWidth / nominalBounds.width;
clip.scaleX = clip.scaleY = scale;
Hope that helps!
I have an image area in my application with width:530px and height:510px. I want to place images in that area but the images comes in different different sizes. how to crop or scale the image without losing aspect ratio to fill that area. Is there any native methods available in winjs?
You have a few options for that.
One is to use the ViewBox control that WinJS provides you. The ViewBox can only have a single child (so you would have your tag as its only child perhaps or a div that contains your img) and it will scale that child (using CSS transforms) up to fit into its container (without changing the aspect ratio). It's pretty slick.
Another option is to set the image as the CSS background-image property of a container (such as a div) and set the background-size property to contain. This will stretch the image up to the size of the container.
A final option that you have to resort to if your case is a bit special is not such a bad option after all. In the updateLayout method of your page, you can refer to the element and explicitly set its CSS properties to fit. At that point you'll know all about the layout and can easily do the math to figure out what size image should be. Here's some code from one of my projects where I do this. Notice that I'm comparing the aspect ratio of the screen and the image to determine whether I should size to the width or the height. Unlike your situation (I'm guessing), my code makes sure the image fills the screen and excess is clipped. I'm guessing you want your img to be contained.
function setImagePosition() {
var img = q(".viewCamera #viewport img");
if (outerWidth/outerHeight > img.naturalWidth/img.naturalHeight) {
img.style.width = format("{0}px", outerWidth);
img.style.height = "";
img.style.top = format("{0}px", (outerHeight - img.clientHeight) / 2);
img.style.left = "0px";
} else {
img.style.width = "";
img.style.height = format("{0}px", outerHeight);
img.style.top = "0px";
img.style.left = format("{0}px", (outerWidth - img.clientWidth) / 2);
}
}
Hope that helps!
Are you referring to scaling HTML images? If so, you can set either one, width or height. Whichever you set, the other will scale and keep image aspect ratio.
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.