How to set line height in Clutter.Text using Pango - gtk

I want to have a Clutter.Text displaying text with double line spacing using Gtk.Pango.
note : in css, we would use line-height: 200% I think.
I tried this code and it didn't work:
var text_actor = new Clutter.Text.with_text ("Roboto 10", "Long long text") ;
text_actor.width= SIDE_PANE_WIDTH ;
text_actor.get_layout ().set_spacing (2*Pango.SCALE) ;
Apparently, Clutter.Text keeps a cached version of the Pango.Layout
Is there a way to achieve this?

One way working around this by using CoglPango directly:
var t = new Clutter.Actor ();
t.set_size (300, 300);
// add some more text to see it
var text = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, ...";
var layout = t.create_pango_layout (text);
layout.set_width (200);
layout.set_spacing (24 * Pango.SCALE);
t.paint.connect (() => {
Cogl.pango_render_layout (layout, 0, 0,
Cogl.Color.from_4ub(0, 0, 0, 255), 0);
});
edit this is indeed the solution. Based on this, here's the code that I used:
actor = new Text () ;
actor.width= SIDE_PANE_WIDTH ;
var text = "Some long text<b>Bold</b>" ;
var pango_layout = bio_actor.create_pango_layout ("");
pango_layout.set_markup (text, text.length) ;
pango_layout.set_spacing (2 * Pango.SCALE);
pango_layout.set_font_description (Pango.FontDescription.from_string ("Roboto 10")) ;
pango_layout.set_width (SIDE_PANE_WIDTH * Pango.SCALE);
bio_actor.paint.connect (() => {
Cogl.pango_render_layout (pango_layout, 0, 0, Cogl.Color.from_4ub(255, 255, 255, 255), 0);
});
int width;
int height ;
pango_layout.get_size (out width, out height) ;
actor.height = height / Pango.SCALE;

Yes, ClutterText caches the PangoLayout instance to avoid having to re-measure text every time it has to retrieve the preferred size. It actually caches the latest three instances of PangoLayout, because of the width-for-height/height-for-width geometry requests, but that's just an implementation detail.
Changing properties on the PangoLayout instance of ClutterText is also not going to result in updates to the ClutterText: you'd have to call clutter_actor_queue_redraw() afterwards, as the PangoLayout sits at a lower level than the actor in the scene graph.
In general, the ClutterText actor does not allow you to tweak the PangoLayout it creates; it's expected that the actor is in charge of creating an modifying the layout, and attempts at overriding that will result in either poor performance or undefined behaviour.
If you want to introduce a line spacing property then you'll have to file a bug against ClutterText — though that would mean that you'd have to wait until September for the next stable release of Clutter.
If you don't need all that ClutterText does, and you just want to display text, you could subclass ClutterActor and use clutter_actor_create_pango_layout() to create a PangoLayout that you can measure inside the overridden get_preferred_width(), get_preferred_height(), and allocate() virtual functions, and paint inside the overridden paint() virtual function.

Related

Make GTK Entry box smaller

I am trying to make a GUI program in Julia using Gtk. My program includes a large number of GtkEntry boxes. However, I am running into space issues because the Entry boxes have a lot of internal padding around the actual characters. I would like to reduce, at least, the top and bottom whitespace. I have tried to use the setproperty!() function to change the height-request value, but that seems to be only able to make the box bigger, not smaller. Additionally, the margin, margin-top, etc. fields are all set to 0 by default. Again, I can make them bigger but not smaller.
Is this possible to fix? I have included below a minimal working example, a screenshot, and a Julia REPL output displaying the available properties.
Edit:
I have also tried using a css file (test.css) with the contents
entry {
margin-top: 0;
margin-bottom: 0;
padding-top: 0;
padding-bottom: 0;
}
Julia 0.6.0 code:
using Gtk
win = GtkWindow("Example")
sb = GtkGrid()
function sb_entry(label)
frame = GtkFrame(label)
entry = GtkEntry()
setproperty!(entry, :input_purpose, 2)
push!(frame, entry)
return frame
end
sb_rows = sb_entry("rows")
sb_cols = sb_entry("cols")
sb_row_off = sb_entry("row off")
sb_col_off = sb_entry("col off")
sb[1,1] = sb_rows
sb[2,1] = sb_cols
sb[1,2] = sb_row_off
sb[2,2] = sb_col_off
setproperty!(sb, :column_homogeneous, true)
setproperty!(sb, :column_spacing, 5)
setproperty!(sb, :row_spacing, 5)
push!(win, sb)
### begin edit (css)
screen = Gtk.GAccessor.screen(win)
provider = GtkCssProviderLeaf(filename="/path/to/test.css")
ccall((:gtk_style_context_add_provider_for_screen, Gtk.libgtk), Void,
(Ptr{Void}, Ptr{GObject}, Cuint),
screen, provider, 1)
### end edit (css)
showall(win)
if !isinteractive()
c = Condition()
signal_connect(win, :destroy) do widget
notify(c)
end
wait(c)
end
julia> sb_row_off[1]
Gtk.GtkEntryLeaf(editing-canceled=FALSE, name="", parent, width-request=-1,
height-request=-1, visible=TRUE, sensitive=TRUE, app-paintable=FALSE,
can-focus=TRUE, has-focus=FALSE, is-focus=TRUE, focus-on-click=TRUE,
can-default=FALSE, has-default=FALSE, receives-default=FALSE, composite-child=FALSE,
style, events=0, no-show-all=FALSE, has-tooltip=FALSE, tooltip-markup=NULL,
tooltip-text=NULL, window, opacity=1.000000, double-buffered, halign=GTK_ALIGN_FILL,
valign=GTK_ALIGN_FILL, margin-left, margin-right, margin-start=0, margin-end=0,
margin-top=0, margin-bottom=0, margin=0, hexpand=FALSE, vexpand=FALSE,
hexpand-set=FALSE, vexpand-set=FALSE, expand=FALSE, scale-factor=2, buffer,
cursor-position=0, selection-bound=0, editable=TRUE, max-length=0, visibility=TRUE,
has-frame=TRUE, inner-border, invisible-char=9679, activates-default=FALSE,
width-chars=-1, max-width-chars=-1, scroll-offset=0, text="", xalign=0.000000,
truncate-multiline=FALSE, shadow-type, overwrite-mode=FALSE, text-length=0,
invisible-char-set=FALSE, caps-lock-warning=TRUE, progress-fraction=0.000000,
progress-pulse-step=0.100000, primary-icon-pixbuf, secondary-icon-pixbuf,
primary-icon-stock, secondary-icon-stock, primary-icon-name=NULL,
secondary-icon-name=NULL, primary-icon-gicon, secondary-icon-gicon,
primary-icon-storage-type=GTK_IMAGE_EMPTY,
secondary-icon-storage-type=GTK_IMAGE_EMPTY, primary-icon-activatable=TRUE,
secondary-icon-activatable=TRUE, primary-icon-sensitive=TRUE,
secondary-icon-sensitive=TRUE, primary-icon-tooltip-text=NULL,
secondary-icon-tooltip-text=NULL, primary-icon-tooltip-markup=NULL,
secondary-icon-tooltip-markup=NULL, im-module=NULL, placeholder-text=NULL,
completion, input-purpose=GTK_INPUT_PURPOSE_DIGITS, input-hints=GTK_INPUT_HINT_NONE,
attributes, populate-all=FALSE, tabs)
entry { min-height: 0px; } allows it to be as small as possible. Adjust size as required.

using an if statement inside button

I am currently stuck on a bit of program, I'm sure there is a way to do it but just can't think of it, so here it goes. so I am using eclipse window viewer and I made a GUI to how I want and I got a Ccombo with a few options to select from, and what I want to do is when a button is clicked I want the program to be able to see what they selected and then depending on what they selected have a different outcome put into another text field
OptionsOptimizer = new Shell();
OptionsOptimizer.setSize(450, 340);
OptionsOptimizer.setText("Options Optimizer");
Label lblSpread = new Label(OptionsOptimizer, SWT.NONE);
lblSpread.setAlignment(SWT.CENTER);
lblSpread.setBounds(10, 10, 213, 15);
lblSpread.setText("Type Of Spread");
CCombo combo = new CCombo(OptionsOptimizer, SWT.BORDER);
combo.setItems(new String[] {"Put Credit Spread", "Short Naked Put", "Put Broken Wing Butterfly", "Custom Naked Put", "Call Debit Spread", "Call Calander", "Call Ratio Backspread", "Put Diagonal", "Short Straddle", "Short Strangle", "Short Iron Condor", "Short Iron Butterfle"});
combo.setBounds(10, 31, 213, 21);
Button Enter = new Button(OptionsOptimizer, SWT.NONE);
Enter.addMouseListener(new MouseAdapter() {
public void mouseDoubleClick(MouseEvent e) {
double profit = Double.parseDouble(Profit.getText());
double margin = Double.parseDouble(Margin.getText());
double roi = profit/margin;
double roundroi = Math.round(roi*10000)/100.0;
ROI.setText("Your return on investment is " + roundroi + "%");
double percent = Double.parseDouble(ITM.getText());
double OTM = ((100 - percent)/100);
int day = Integer.parseInt(Days.getText());
double roc = (roi/day)*OTM;
double roundroc = Math.round(roc*10000)/100.0;
ROC.setText("Your return on capital per day is " + roundroc + "%");
double annual = roc*365*.4;
double roundannual = Math.round(annual*10000)/100.0;
Annual.setText("Your annual return is " + roundannual + "% if you invested 40% of your total equity");
Point spread = combo.getSelection();
if(spread.toString() == "Put Credit Spread")
{
Volitility.setText("A fall in implied volitility will help your position");
}
});
Enter.setBounds(159, 108, 75, 25);
Enter.setText("Evaluate");
}
I can see one problem with your code: Your are comparing the text of the Button using ==, but you should be using spread.toString().equals("Put Credit Spread").
See How do I compare strings in Java? for more information.
As a bit of advice: CCombo has a getSelectionIndex function that returns a integer value of the selected item beginning at 0, or -1 if no item is selected. Using this function would have the benefit of beeing able to change the Item text without needing to change the logic aswell.

sap.ui.table.Table "VisibleRowCountMode.Auto" mode does not work

I'm having trouble setting the number of rows for a table to automagically fill the available estate of its encapsulating container.
According to the API, setting the visibleRowCountMode property to sap.ui.table.VisibleRowCountMode.Auto should render the table to
"[...] automatically fills the height of the surrounding container.
The visibleRowCount property is automatically changed accordingly. All
rows need the same height, otherwise the auto mode doesn't always work
as expected."
I have used the following code:
var oTable = new sap.ui.table.Table( {
rowHeight : 30,
height : "100%",
// The below property is seemingly ignored... What did I do wrong?
visibleRowCountMode : sap.ui.table.VisibleRowCountMode.Auto
});
...but as you can see in this jsbin example http://jsbin.com/vazuz/1/edit it just shows the default 10 rows, and certainly doesn't "change the visibleRowCount property accordingly" :-(
Anyone has a solution?
Thanks in advance!
=====================
EDIT: Thanks to #matz3's answer below, I was ultimately able to solve this issue.
Setting the surrounding container DIV to 100%, this seems to be ignored. Setting it to a fixed height, however, worked just fine. But what I really wanted, if a user resized the window, the number of available rows needs to be adjusted accordingly. Setting it to a fixed height is therefor not an option...
However, the trick was in some extra CSS: not only the DIV needed to be set to 100% height, also both BODY and HTML (!!) needed to have a height set to 100%:
html, body {
height: 100%
}
div#uiArea {
height: 100%
}
Now, the table spans the full height of the available viewport, and resizing the window adjusts the table rather nicely. See the final working solution here: http://jsbin.com/bosusuya/3/edit
Matz3, thanks for your help!
CSS hacks is a dirty way. In my application I use to bind visibleRowCount to Array.length
For example, if you have model with this data:
[{firstName: 'John', lastName: 'Smith',
{firstName: 'David', lastName: 'Ericsson'}]
You can bind to Array property length like this:
var oTable = new sap.ui.table.Table({
visibleRowCount : '{/length}'
})
[...] automatically fills the height of the surrounding container [...]
Your surrounding container is the view, so you have to set the height of it also to a value (e.g. 100%)
this.setHeight("100%");
And your view will be set into the uiArea-div, so this one also needs a height (e.g. 500px)
<div id="uiArea" style="height:500px"></div>
With these changes it now works as expected
I'm with the same issue. I "resolve" that in this manner. This is not perfect, but it's better than UI5 resizing...
  _resizeTableRow: function () {
var oTable = this.getView().byId("referenceTabId");
var sTop = $('#' + oTable.getId()).offset().top;
var sHeight = $(document).height();
//if there a row, you can take the row Height
//var iRowHeight = $(oTable.getAggregation("rows")[0].getDomRef()).height();
var iRowHeight = 40;
var iRows = Math.trunc((sHeight - sTop ) / iRowHeight);
oTable.setVisibleRowCount(iRows);
   },
Other option is to put the Table in sap.ui.layout.Splitter:

nvd3 space between bars

I've made a MultiBarChart with NVD3.
It works, however, a colleague said I needed more space between each Australian state.
So, Tasmania further from Victoria etc.
Here is the data visualisation
I can not find a forum that explains this in non-developer language. I'm not a developer, but having a go.
Here is my code...
var chart;
nv.addGraph(function() {
chart = nv.models.multiBarHorizontalChart()
.x(function(d) { return d.label })
.y(function(d) { return d.value })
.margin({top: 30, right: 105, bottom: 30, left: 103})
.tooltips(true)
.showControls(false);
chart.yAxis
.tickFormat(d3.format(',.1f'));
d3.select('#chart1 svg')
.datum(long_short_data)
.transition().duration(1400)
.call(chart);
nv.utils.windowResize(chart.update);
chart.dispatch.on('stateChange', function(e) { nv.log('New State:', JSON.stringify(e)); });
return chart;
});
Thanks you super kind and smart people!
No Need to use too much code for spacing just use below code :
var chart = nv.models.multiBarChart();
//added by santoshk for fix the width issue of the chart
chart.groupSpacing(0.8);//you can any value instead of 0.8
This is unfortunately something you can't configure in NVD3. However, you can change the height of the bars after the chart has been created to make it appear as if there's more space between them. The code to do this is simple:
d3.selectAll(".nv-bar > rect").attr("height", chart.xAxis.rangeBand()/3);
The default height is chart.xAxis.rangeBand()/2 -- you can adjust this as you see fit. The only thing to keep in mind when running this code is that NVD3 animates its elements, so not everything will be there in the beginning or values may be overwritten. You can solve this by waiting a small amount of time before calling that code using setTimeout:
setTimeout(function() {
d3.selectAll(".nv-bar > rect").attr("height", chart.xAxis.rangeBand()/3);
}, 100);
Just found this question while searching for a way to add more space between bars. Like Lars said, you can change the bar size after the chart has been drawn. However, when you increase the bar height without changing the space between each bar, it overflows. To add space between the bars you should use xRange:
var chart = nv.models.multiBarHorizontalChart().xRange([0, 125])

GooCanvas (Perl GTK2, Goo::Canvas) : Moving path (line) while bound to one point, adding text-box, and connecting it with other canvas items.

I am new to GooCanvas library. Currently using Perl::Gtk2 and Goo::Canvas module.
By looking at code, from demo examples, I can draw primary canvas items, bind keyboard and mouse events (like drag, focus, move) to them.
Now, I want to manipulate path little bit further. Below is code for path (line):
my $objLine = Goo::Canvas::Path->new(
$root,
"M 20 20 L 80 80",
'width' => 10.0,
'stroke-color' => 'black',
# 'fill-color' => 'red',
'can-focus' => TRUE
);
$objLine->{id} = "Line";
$objLine->signal_connect('focus_in_event' => \&on_focus_in);
$objLine->signal_connect('focus_out_event' => \&path_on_focus_out);
$objLine->signal_connect('key_press_event' => \&on_key_press);
$objLine->signal_connect('motion_notify_event', \&on_motion_notify);
$objLine->signal_connect('button_press_event', \&on_button_press);
$objLine->signal_connect('button_release_event', \&on_button_release);
There are three things, which I want do:
How do I move, extend line while it is fixed to a particular point.
I want to bound a text box to it. I tried doing that with other items, but when items moves, text box remains at its original position.
Using path(line) to connect other canvas items.
I am not asking for direct code (example might be appreciative), but required logic, and name of goocanvas functions(method/property).
Use a GooCanvasGroup, make it parent of all your items which are supposed to be moved as a unit and move the group around by setting its position.
Quick ripof C example from the devhelp manual – modifying a line by changing the coords of one end
line =
goo_canvas_polyline_new_line
(yourgroup,
100.0, 100.0,
300.0, 100.0,
"stroke-color", "red",
"line-width", 5.0,
NULL);
to update the position (or even just one end of a 2 dot wire)
GooCanvasPoints *points = NULL;
g_object_get (line, "points", &points);
// modify "points" as you need to update its position
// it may be needed to re-set the "points" property via
g_object_set (line, "points", points);
if you want to move a GooCanvasGroup
g_object_set (group, "x", new_x_pos, "y", new_y_pos, NULL);