How Can i Know the current blockchain height from RIDE? - wavesplatform

I need to know the current height of the blockchain from a RIDE script and add to the current height more or less the height of one week. I tried this:
let currentHeight = transactionHeightById(i.transactionId)
let finishHeight = currentHeight + (7*1440)
Is this the correct/best way? Also when trying to get finishHeight I am getting this error:
Compilation failed: Can't find a function overload '+'(Int|Unit, Int) in 952-974

The current WAVES blockchain height in RIDE is contained in the variable height.
So for knowing the current height and add about a week time (in height) to it:
[...]
else if (contestStartHeight <= height) then throw("Start Height must be greater than current Blockchain height: " + toString(height))
else {
let contestFinishHeight = contestStartHeight + (7*1440)
}
[...]

Related

Angular9 Signature Pad issue: Signature drawn offset from pen touch

I implemented a signature pad using https://github.com/ramsatt/Angular9SignaturePad/tree/master/src/app/_componets/signature-pad and it works fine on smaller devices but on iPad or bigger devices like 7" upwards, it doesn't work properly.
When drawing on the screen, the resulting line has an offset from where the user touched (Signature drawn doesn't appear directly under the pen as user draws).
please how can I fix this.
So I fixed it by adding the below code and calling it in ngOnInit
resizeCanvas() {
var width = this.signaturePadElement.nativeElement.width;
var height = this.signaturePadElement.nativeElement.height;
var ratio = Math.max(window.devicePixelRatio || 1, 1);
if (ratio <= 2) {
this.signaturePadElement.nativeElement.width = width * ratio;
this.signaturePadElement.nativeElement.height = height * ratio;
this.signaturePadElement.nativeElement
.getContext("2d")
.scale(ratio, ratio);
}
then do
ngOnInit(){
this.resizeCanvas()
}
this.signaturePadElement is your Element gotten using ViewChild()

Working with PDFKit: How to make page breaks?

Looking for some direction
I'm working with PDFKit. Everything is going fine but having trouble finding the methods (documentation / WWDC / elsewhere ) on how to stop text from drawing at a certain y position and start the next page. Any saved references or a snippet of code would be a great help.
I dont know, wether this is the best way to implement your use case, but it worked for me.
When adding a new line into the PDF_Context, I recalculate a variable the keeps tracking of the current content height of my PDF_Page. When it exceeds a certain value, I create a NEW page, set the content height to zero and go on filling, ...
And you might wanna find some good answers, practices HERE -> RayWenderlich.
// my initial value
private var myCurrentPageContentHeight: CGFloat = 20
// in your PDF fill procedures add something like
myCurrentPageContentHeight += 40
// I also have a struct the encapsulates
// PageSize with padding, ...
enum PDF_PageSize {
case din_A4_Portrait
case din_A4_Landscape
// -------------------------------
// getPDF_TotalRect
// -------------------------------
func getPDF_TotalRect() -> CGRect {
switch self {
case .din_A4_Portrait : return CGRect(x: 0, y: 0, width: 595, height: 842)
case .din_A4_Landscape : return CGRect(x: 0, y: 0, width: 842, height: 595)
}
}
// ....
}

GtkFlowBox do NOT align in columns using horizontal orientation

In GTK I am trying to align widgets of different widths in a box such that they are next to each other in a line and flow into the next line if no more space is left. Basically I am trying to get similar results to Qt's Flow Layout as seen here:
(Source: This Qt documentation page)
I need each widget to be as small (width-wise) as possible, even allowing widths of only 20 pixels.
To automatically go to the next line if more space is needed, GTK provides the GtkFlowBox. My problem here is that it appears like the GtkFlowBox aligns all widgets in a grid of a dynamic width (cell-wise). The following image shows that even very wide widgets force widgets directly below it to use the exact same width:
(Mind that each "..." is in its own Label just like each text sequence.)
In the picture the second long label clearly results in the last label getting much more space than needed. The GTK documentation did not really make it clear to me that the GtkFlowBox works like a dynamic grid, but other images in the internet also show a grid-wise alignment everytime.
I am searching for a way where Widgets flow into the next row if there is no space left but all rows are independent from each other in other aspects. Qt appears to achieve this as the last button would contradict the widgets being aligned in a grid.
Is there a way achieving what I am trying with GtkFlowBox, or with another existing Layout, or only by manually implementing it? I think that the easiest manual way would be to use horizontal Boxes and dynamically map the widgets to different boxes so that no box is overfull. But clearly this would be drastically less easy and elegant than using an existing Layout.
(Note in case that anyone has a third-party solution written for specific environments: I am working with Rust (Gtk-rs))
The solution to my problem was implementing my own container. I want to try documenting how to approach this problem and will provide my code here.
The main concept is subclassing a container. This guide gives a good overview using C. The main ideas can easily be transferred to other languages if you inform yourself about subclassing in your language binding. There are two main problems to solve. One is the size-calculation needed for the container. The other one is how the children actually are aligned in the container.
Regarding the size-calculation, the request mode should be set to HeightForWidth as the width influences how many children fit into the rows and therefore also how many rows are needed. A problem here is that while larger widths imply smaller heights vice versa, gtk uses the minimum width to calculate the minimum height. This problem is documented in this post. I solved it by adding a property indicating how many children should be placed in one row at least such that the actual width can be approximated yielding acceptable height requirements. My get_preferred_width assumes that the minimum number of children is placed in each row to calculate the minimum width. A more natural approach would be to set it to the width of the largest child, but this results in a much larger minimum height. get_preferred_height_for_width directly depends on the allocation algorithm that it uses without really allocating size for its children.
I ran into some problems implementing the size allocation regarding minimum and natural sizes. It is not possible to use space remaining when using the minumum height evenly among the children to reach natural size in standard ways as children may flow to other rows at any time and the distribution shall be fair globally and not only per row. I assign the minimum width to each child and add a ratio of the width remaining to reach the natural width which is the same for all children. Due to reflowing, I found no nice algorithm to do this not being simple trial and error. Thus, I just try if the available height is enough for different ratios where I test those ratios down to a sufficiently low resolution. This yields a tradeoff between quality and efficiency. I use binary search to make it somehow efficient.
If you have any specific questions, feel free to ask. As code examples, I want to provide a third party solution in C which user James Westman proposed in my other post. I wanted to provide it as my own code is in Rust. Thus, it could be useful regarding the ideas while for instance the subclassing has a lot of differences to subclassing with gtk in C making it non-trivial just to use this code in other languages. My example also contains a dummy container allowing to test different natural and minumum sizes of the container's children. It works as standalone. Also mind that some functionality is not contained in the latest stable release of gtk-rs, use the newest version by e.g.
[dependencies.gtk]
git = "https://github.com/gtk-rs/gtk"
(Code in another answer as answer size is limited and I cannot share the git repo in the moment)
Read the description in another answer first. This code is excluded as the answer length is limited; the code and the text won't fit into one.
#[macro_use]
extern crate glib;
extern crate gdk;
extern crate gio;
extern crate gtk;
use gio::prelude::*;
use glib::subclass;
use glib::subclass::prelude::*;
use glib::translate::*;
use gtk::prelude::*;
mod dummy {
use super::*;
glib_wrapper! {
pub struct GAspectFillFrame(
Object<subclass::simple::InstanceStruct<internal::GAspectFillFrame>,
subclass::simple::ClassStruct<internal::GAspectFillFrame>,
SimpleAppWindowClass>)
#extends gtk::Bin, gtk::Container, gtk::Widget;
match fn {
get_type => || internal::GAspectFillFrame::get_type().to_glib(),
}
}
impl GAspectFillFrame {
pub fn new() -> GAspectFillFrame {
glib::Object::new(GAspectFillFrame::static_type(), &[])
.expect("Failed to create GAspectFillFrame instance")
.downcast::<GAspectFillFrame>()
.unwrap()
}
}
mod internal {
use super::*;
use gtk::subclass::{bin::BinImpl, container::ContainerImpl, widget::WidgetImpl};
use gtk::SizeRequestMode;
pub struct GAspectFillFrame {}
static PROPERTIES: [subclass::Property; 0] = [];
impl ObjectSubclass for GAspectFillFrame {
const NAME: &'static str = "GAspectFillFrame";
type ParentType = gtk::Bin;
type Instance = subclass::simple::InstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
glib_object_subclass!();
fn class_init(klass: &mut Self::Class) {
klass.install_properties(&PROPERTIES);
}
fn new() -> Self {
Self {}
}
}
impl ObjectImpl for GAspectFillFrame {
fn set_property(&self, _obj: &glib::Object, _id: usize, _value: &glib::Value) {
panic!();
}
fn get_property(&self, _obj: &glib::Object, _id: usize) -> Result<glib::Value, ()> {
panic!();
}
}
impl WidgetImpl for GAspectFillFrame {
fn get_preferred_width(&self, _widget: &gtk::Widget) -> (i32, i32) {
(50, 100)
}
fn get_preferred_height(&self, _widget: &gtk::Widget) -> (i32, i32) {
(50, 100)
}
fn get_request_mode(&self, _widget: &gtk::Widget) -> gtk::SizeRequestMode {
SizeRequestMode::ConstantSize
}
}
impl ContainerImpl for GAspectFillFrame {}
impl BinImpl for GAspectFillFrame {}
impl GAspectFillFrame {}
}
}
glib_wrapper! {
/// A container displaying its children rowwise and dynamically reflowing children to the next row
/// if there is no space left. In contrast to the `gtk::FlowBox` this container will not act like a grid and instead will
/// display its rows independent of each other besides of the assignment of the children to the rows.
///
/// The container allows to set the horizontal spacing between children and the vertical spacing between rows.
///
/// While the height of the container is queried for given widths as an increase in the latter decreases the height,
/// gtk uses the minimal width to calculate the minimal height. This could result in unexpected large heights.
/// This behaviour can be controlled by influencing the minimal width such that it is reasonably high.
/// To do so, set the `min-row-children` property. Using it to require a row to be able to contain a minimum of children which is
/// higher than the default value `1` leads to higher minimum widths and therefore also smaller minimum heights.
/// Note that the property is used for min width calculations but not actually enforced in size allocation.
/// It is a soft limit to allow an easier front to back calculation for the allocation.
/// Requiring a minimal number of children per line would imply new problems, as the minimum width calculation places a constant number
/// of elements in one line while the real allocation does more calculations allowing a non constant number.
/// Setting the min number of children as a hard limit could lead to situations where a for the min width calculations e.g. 4 children
/// are in each row while for the real allocation one row may have some remaining place for one more child than necessary.
/// In this case, the child would be in this row, the next row requires another child to reach the hard limit which could then overflow
/// the row if it had a large size.
/// Note that while the property is not enforced in final allocation, the min space requirements always are sufficient to place
/// all children with their min width or larger.
///
/// The container expands h-expand children with respect to the remaining space in their row which is evenly
/// distributed among all expanding children of that row.
///
/// In the case where the natural size requirements of the children cannot be satisfied, the container tries
/// to set their size such that they get their minimal size and an additional fraction/ratio of the difference between
/// their minimal and natural size such that this fraction is constant among all children.
/// Note that this operation is non-trivial as changes in this ratio may lead to children being shifted into
/// different rows and as rows may have some remaining space if others are full.
/// The implemented solution implements a tradeoff between a visually nice rescaling behaviour and efficiency.
pub struct ProperFlowBox(
Object<subclass::simple::InstanceStruct<internal::ProperFlowBox>,
subclass::simple::ClassStruct<internal::ProperFlowBox>,
SimpleAppWindowClass>)
#extends gtk::Container, gtk::Widget;
match fn {
get_type => || internal::ProperFlowBox::get_type().to_glib(),
}
}
impl ProperFlowBox {
/// Creates a new instance
pub fn new() -> ProperFlowBox {
glib::Object::new(ProperFlowBox::static_type(), &[])
.expect("Failed to create ProperFlowBox instance")
.downcast::<ProperFlowBox>()
.unwrap()
}
/// Sets the spacing between two children in a line and between children and the container's borders
///
/// # Arguments
///
/// * `spacing` - Horizontal spacing in pixels
pub fn set_h_spacing(&self, spacing: i32) {
self.set_property("h-spacing", &spacing)
.expect("Error setting h-spacing of ProperFlowBox");
}
/// Sets the spacing between two rows and between children and the container's borders
///
/// # Arguments
///
/// * `spacing` - Vertical spacing in pixels
pub fn set_v_spacing(&self, spacing: i32) {
self.set_property("v-spacing", &spacing)
.expect("Error setting v-spacing of ProperFlowBox");
}
/// Sets the minimum number of children used to approximate the required width
///
/// The set property is not enforced by the size allocation.
/// Setting this to higher values may result in less required minimum height of the container.
///
/// # Arguments
///
/// * `min_children` - Minimum number of children per row
pub fn set_min_row_children(&self, min_children: u32) {
self.set_property("min-row-children", &min_children)
.expect("Error setting min-row-children of ProperFlowBox");
}
}
mod internal {
use std::cell::RefCell;
use super::*;
use gtk::subclass::{
container::Callback,
container::ContainerImpl,
widget::{WidgetImpl, WidgetImplExt},
};
const DEFAULT_MIN_ROW_CHILDREN: u32 = 5;
pub struct ProperFlowBox {
children: RefCell<Vec<gtk::Widget>>,
h_spacing: RefCell<i32>,
v_spacing: RefCell<i32>,
min_row_children: RefCell<u32>,
}
static PROPERTIES: [subclass::Property; 3] = [
subclass::Property("h-spacing", |h_spacing| {
glib::ParamSpec::int(
h_spacing,
"Horizontal spacing",
"Space between two children in a row and between children and the container's borders",
0,
i32::MAX,
0,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("v-spacing", |v_spacing| {
glib::ParamSpec::int(
v_spacing,
"Vertical spacing",
"Space between two rows and between rows and the container's borders",
0,
i32::MAX,
0,
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("min-row-children", |min_row_children| {
glib::ParamSpec::uint(
min_row_children,
"Minimal number of children in one row",
"Setting this to larger numbers increases the minumum width and decreases the minimum height",
1,
u32::MAX,
DEFAULT_MIN_ROW_CHILDREN,
glib::ParamFlags::READWRITE,
)
}),
];
impl ObjectSubclass for ProperFlowBox {
const NAME: &'static str = "ProperFlowBox";
type ParentType = gtk::Container;
type Instance = subclass::simple::InstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
glib_object_subclass!();
fn class_init(klass: &mut Self::Class) {
klass.install_properties(&PROPERTIES);
}
fn new() -> Self {
Self {
children: RefCell::new(Vec::new()),
h_spacing: RefCell::new(0),
v_spacing: RefCell::new(0),
min_row_children: RefCell::new(DEFAULT_MIN_ROW_CHILDREN),
}
}
}
impl ObjectImpl for ProperFlowBox {
fn set_property(&self, _obj: &glib::Object, id: usize, value: &glib::Value) {
let prop = &PROPERTIES[id];
match *prop {
subclass::Property("h-spacing", ..) => {
*self.h_spacing.borrow_mut() = value.get_some().unwrap();
}
subclass::Property("v-spacing", ..) => {
*self.v_spacing.borrow_mut() = value.get_some().unwrap();
}
subclass::Property("min-row-children", ..) => {
*self.min_row_children.borrow_mut() = value.get_some().unwrap();
}
_ => panic!("Tried to set unknown property of ProperFlowBox"),
}
}
fn get_property(&self, _obj: &glib::Object, id: usize) -> Result<glib::Value, ()> {
let prop = &PROPERTIES[id];
match *prop {
subclass::Property("h-spacing", ..) => Ok(self.h_spacing.borrow().to_value()),
subclass::Property("v-spacing", ..) => Ok(self.v_spacing.borrow().to_value()),
subclass::Property("min-row-children", ..) => {
Ok(self.min_row_children.borrow().to_value())
}
_ => panic!("Tried to get unknown property of ProperFlowBox"),
}
}
fn constructed(&self, obj: &glib::Object) {
self.parent_constructed(obj);
obj.downcast_ref::<gtk::Widget>()
.unwrap()
.set_has_window(false);
}
}
impl WidgetImpl for ProperFlowBox {
fn size_allocate(&self, widget: &gtk::Widget, allocation: &gtk::Allocation) {
self.parent_size_allocate(widget, &allocation);
// Search for maximal working natural ratio.
// Sort out most likely cases (enough for 1.0 or not for more than 0.0) and do
// binary search otherwise.
if self.check_height_for_natural_ratio(allocation.width, 1.0, false)
<= allocation.height
{
// Do 1.0
self.check_height_for_natural_ratio(allocation.width, 1.0, true);
} else if self.check_height_for_natural_ratio(allocation.width, 0.0, false)
>= allocation.height
{
// Do 0.0
self.check_height_for_natural_ratio(allocation.width, 0.0, true);
} else {
// Do binary search
// A lower stopping eps yields higher quality by finer transitions but less performance.
// 0.001 should be a reasonable tradeoff as binary search implies that ca. log_2(0.25/0.001) ~= 8 iterations.
let mut current_ratio = 0.5;
let mut current_step_width = 0.25;
const STOPPING_EPS: f64 = 0.001;
let mut max_ratio: f64 = 0.0;
while current_step_width > STOPPING_EPS {
let required_height =
self.check_height_for_natural_ratio(allocation.width, current_ratio, false);
if allocation.height >= required_height {
max_ratio = max_ratio.max(current_ratio);
current_ratio += current_step_width;
} else {
current_ratio -= current_step_width;
}
current_step_width /= 2.0;
}
self.check_height_for_natural_ratio(allocation.width, max_ratio, true);
}
}
fn get_request_mode(&self, _widget: &gtk::Widget) -> gtk::SizeRequestMode {
gtk::SizeRequestMode::HeightForWidth
}
fn get_preferred_height(&self, widget: &gtk::Widget) -> (i32, i32) {
widget.get_preferred_height_for_width(widget.get_preferred_width().0)
}
fn get_preferred_width_for_height(&self, widget: &gtk::Widget, _height: i32) -> (i32, i32) {
widget.get_preferred_width()
}
fn get_preferred_width(&self, _widget: &gtk::Widget) -> (i32, i32) {
// Calculate an approximation of the required width by exactly placing `min_row_children` many
// children in each row
let mut min_width = 0;
let mut natural_width = 0;
let mut current_min_width = 0;
let mut current_natural_width = 0;
for (index, child) in self
.children
.borrow()
.iter()
.filter(|c| c.is_visible())
.enumerate()
{
if index as u32 % *self.min_row_children.borrow() == 0 {
// Begin a new row
current_min_width = *self.h_spacing.borrow();
current_natural_width = *self.h_spacing.borrow();
}
current_min_width += child.get_preferred_width().0 + *self.h_spacing.borrow();
current_natural_width += child.get_preferred_width().1 + *self.h_spacing.borrow();
// Max each time for more consistent code as last row may not contain `min_row_children` children
min_width = min_width.max(current_min_width);
natural_width = natural_width.max(current_natural_width);
}
(min_width, natural_width)
}
fn get_preferred_height_for_width(&self, _widget: &gtk::Widget, width: i32) -> (i32, i32) {
(
self.check_height_for_natural_ratio(width, 0.0, false),
self.check_height_for_natural_ratio(width, 1.0, false),
)
}
}
impl ContainerImpl for ProperFlowBox {
fn add(&self, container: &gtk::Container, widget: &gtk::Widget) {
self.children.borrow_mut().push(widget.clone());
widget.set_parent(container);
if container.get_visible() {
container.queue_resize();
}
}
fn remove(&self, container: &gtk::Container, widget: &gtk::Widget) {
let index = self.children.borrow().iter().position(|c| c == widget);
if let Some(index) = index {
self.children.borrow_mut().remove(index);
widget.unparent();
} else {
println!("Tried to remove non-child from ProperFlowBox")
}
if container.get_visible() {
container.queue_resize();
}
}
fn forall(
&self,
_container: &gtk::Container,
_include_internals: bool,
callback: &Callback,
) {
// Need to deepcopy children as callbacks may also borrow children
let children = (*self.children.borrow()).clone();
for child in children.iter() {
callback.call(child);
}
}
}
impl ProperFlowBox {
/// Tries to fit the visible children for the given available width.
///
/// Given the available width, all visible children get their minimum size plus
/// the fraction defined by `natural_ratio` of the additional size bringing them to
/// their natural size. The function then returns the required height for the given width.
/// It is possible to directly call `size_allocate` for the visible children by enabling
/// it with the corresponding parameter. Real allocating also respects the `h-expand` property
/// of the children which does not influence the returned height of the function.
///
/// # Arguments
///
/// * `available_width` - Width available to be filled
/// * `natural_ratio` - Fraction of the additional size to meet the natural size coming from the minimum size.
/// For a ratio `x` the allocated width and height will be `min + x * (max - min) == (1 - x) * min + x * max`
/// * `allocate` - Call `size-allocate` on visible children if true
fn check_height_for_natural_ratio(
&self,
available_width: i32,
natural_ratio: f64,
allocate: bool,
) -> i32 {
// Coordinates of next child
let mut x = *self.h_spacing.borrow();
let mut y = *self.v_spacing.borrow();
let mut line_height = 0;
let mut number_row_children = 0;
let mut number_hexpand_row_children = 0;
let mut row_start_index = 0;
for (index, child) in self
.children
.borrow()
.iter()
.enumerate()
.filter(|(_, c)| c.is_visible())
{
let width = ProperFlowBox::get_barycentric_combination(
child.get_preferred_width(),
natural_ratio,
);
let height = ProperFlowBox::get_barycentric_combination(
match child.get_request_mode() {
gtk::SizeRequestMode::ConstantSize => child.get_preferred_height(),
gtk::SizeRequestMode::HeightForWidth
| gtk::SizeRequestMode::WidthForHeight => {
child.get_preferred_height_for_width(width)
}
_ => panic!("Unknown size request mode"),
},
natural_ratio,
);
if number_row_children > 0 && x + width + *self.h_spacing.borrow() > available_width
{
// Not enough space in current line => Go to next line
// Exception: Current child will be only one in line, then assign as there is no
// valid assignment to any line for this child
// Allocate finished line
if allocate {
self.allocate_row(
&self.children.borrow()[row_start_index..index],
y,
line_height,
number_hexpand_row_children,
available_width - x,
natural_ratio,
);
}
// Start next line
x = *self.h_spacing.borrow();
y += line_height + *self.v_spacing.borrow();
line_height = 0;
number_row_children = 0;
number_hexpand_row_children = 0;
row_start_index = index;
}
line_height = line_height.max(height);
x += width + *self.h_spacing.borrow();
number_row_children += 1;
if child.get_hexpand() {
number_hexpand_row_children += 1;
}
}
// Allocate last line
if allocate {
self.allocate_row(
&self.children.borrow()[row_start_index..],
y,
line_height,
number_hexpand_row_children,
available_width - x,
natural_ratio,
);
}
y + line_height + *self.v_spacing.borrow()
}
/// Allocates the size for the children in the given slice
///
/// # Arguments
///
/// * `children` - Slice of which the visible children inside form a row
/// * `y` - y coordinate of the row
/// * `height` - height of the row
/// * `number_hexpand_children` - Number of children with h-expand
/// * `remaining_space` - Unneeded space to be distributed among h-expand children
/// * `natural_ratio` - Fraction of the additional size to meet the natural size coming from the minimum size.
/// For a ratio `x` the allocated width and height will be `min + x * (max - min) == (1 - x) * min + x * max`
fn allocate_row(
&self,
children: &[gtk::Widget],
y: i32,
height: i32,
number_hexpand_children: i32,
remaining_space: i32,
natural_ratio: f64,
) {
let mut x = *self.h_spacing.borrow();
let additional_width_per_child = if number_hexpand_children > 0 {
remaining_space / number_hexpand_children
} else {
0
};
for child in children.iter().filter(|c| c.is_visible()) {
let mut width = ProperFlowBox::get_barycentric_combination(
child.get_preferred_width(),
natural_ratio,
);
if child.get_hexpand() {
width += additional_width_per_child;
}
child.size_allocate(&gtk::Allocation {
x,
y,
width,
height,
});
x += width + *self.h_spacing.borrow();
}
}
/// Returns the barycentric combination of `min` and `max` with the given ratio,
/// namely `min + ratio * (max - min) == (1 - ratio) * min + ratio * max`
///
/// # Arguments
///
/// * `min` - Min value
/// * `max` - Max value
/// * `ratio` - barycentric parameter, should be in `[0,1]` such that result is in `[min,max]`
fn get_barycentric_combination((min, max): (i32, i32), ratio: f64) -> i32 {
((1.0 - ratio) * min as f64 + ratio * max as f64) as i32
}
}
}
fn main() {
let application = gtk::Application::new(None, Default::default())
.expect("Failed to initialize GTK application");
application.connect_activate(|app| {
let window = gtk::ApplicationWindow::new(app);
window.set_title("Custom FlowBox Demo");
let style = ".bordered {border: 1px solid black;}";
let provider = gtk::CssProvider::new();
provider
.load_from_data(style.as_bytes())
.expect("Failed to load CSS");
gtk::StyleContext::add_provider_for_screen(
&gdk::Screen::get_default().expect("Failed to load css provider"),
&provider,
gtk::STYLE_PROVIDER_PRIORITY_APPLICATION,
);
let flow = ProperFlowBox::new();
flow.set_h_spacing(10);
flow.set_v_spacing(10);
for i in 1..15 {
let dummy = dummy::GAspectFillFrame::new();
let label = gtk::Label::new(Some("Hello world"));
dummy.add(&label);
if i % 3 == 0 {
dummy.set_hexpand(true);
}
label.get_style_context().add_class("bordered");
flow.add(&dummy);
}
window.add(&flow);
window.show_all();
});
application.run(&[]);
}
The solution I found for this problem on my program was to:
Have the FlowBox inside a regular Box oriented horizontally
Set that box's hexpand property to TRUE
Set to 2 the minimum amount of items per line of the flow box
I had to do things this way because setting the FlowBox hexpand to TRUE would make its items to get more spacing the more I resized the window. And if had I set the minimum amount of items per line to 1, then I would have always one item per line.
Doing things the way I described make the FlowBox to have as many items per line as there is space available in the window, while having no extra space added between items when increasing the window. To be really honest, I do not know why this worked.
What I was doing in my program was to create radio buttons for options, and get the buttons to flow to the next line once there is not enough space in the horizontal. Here are the relevant parts of my code (in C):
// Create the wrapper box to hold the entry's widgets (name label and options)
GtkWidget *my_wrapper = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, ENTRY_VERTICAL_SPACING);
gtk_widget_set_hexpand(my_wrapper, TRUE);
// Create a name label with the string on the text buffer
GtkWidget *my_name_label = gtk_label_new(text_buffer);
gtk_widget_set_valign(my_name_label, GTK_ALIGN_START);
gtk_widget_set_margin_end(my_name_label, ENTRY_HORIZONTAL_SPACING);
gtk_widget_set_margin_top(my_name_label, 8); // Added some top margin so the label's text align with the options
// (for whatever reason, just aligning both to the top was not enough)
// Create a flow box for the options
GtkWidget *my_options = gtk_flow_box_new();
gtk_widget_set_valign(my_options, GTK_ALIGN_START);
gtk_flow_box_set_min_children_per_line(GTK_FLOW_BOX(my_options), 2);
// Add the flow box to the wrapper
gtk_container_add(GTK_CONTAINER(my_wrapper), my_options);
// Radio button
GtkWidget *my_radio_button = NULL;
GtkWidget *previous_button = NULL;
// Loop for creating and adding the radio buttons
/* for/while (some condition) */
{
char *my_text = /* Option's text according to the condition */ ;
my_radio_button = gtk_radio_button_new_with_label(NULL, my_text);
gtk_radio_button_join_group(GTK_RADIO_BUTTON(my_radio_button), GTK_RADIO_BUTTON(previous_button));
previous_button = my_radio_button;
gtk_container_add(GTK_CONTAINER(my_options), my_radio_button);
}

AXUIElement value attributes

I want to set exterior app's frame from my own project and I found a problem:
I can set its size and its position (but the thing is, I want it to be full screen, and even if I set the size to be full screen it does not set it's size to it (I have to press the button several times).
I think the problem is with its frame.
var frame = CGRectMake(0.0, 23.0, 1280.0, 770.0) //I post only this as size and position seem to work
let sizeCoo: AXValue = AXValueCreate(AXValueType(rawValue: kAXValueCGSizeType)!, &size)!.takeRetainedValue()
let positionCoo: AXValue = AXValueCreate(AXValueType(rawValue: kAXValueCGPointType)!, &position)!.takeRetainedValue()
let frameCoo: AXValue = AXValueCreate(AXValueType(rawValue: kAXValueCGRectType)!, &frame)!.takeRetainedValue()
let errorFrame = AXUIElementSetAttributeValue(myApp, "AXFrame", frameCoo)
Setting sizeCoo and positionCoo give me an error with raw value = 0 - everythng is ok, but setting frameCoo displays an error with rawValue = -25205 which means:
/*! The attribute is not supported by the AXUIElementRef. */
kAXErrorAttributeUnsupported = -25205
and I clearly see when I list attributes for this window there is the "AXFrame" attribute.
What am I doing wrong?

Having a dynamic number of standalone views divide the space evenly

When showing multiple instances of the same view, I would like the following to hold true:
The views do not stack
The number of them is dynamic (let's say 1 to 10) and not known initially: they are added by the user, one by one
They are positioned above/below each other
They take up all the vertical space amongst themselves
By default they have equal height (if there are 3 views, each gets 1/3 of the total vertical space, adding a 4th view causes them all to get 1/4 etc)
What I use to add the views in Perspective is the following:
public void createInitialLayout(IPageLayout layout) {
String editorArea = layout.getEditorArea();
layout.addStandaloneViewPlaceholder(MarkerView.VIEW_ID + ":0", IPageLayout.TOP, 0.6F, editorArea, true);
layout.addStandaloneViewPlaceholder(MarkerView.VIEW_ID + ":1", IPageLayout.BOTTOM, 0.6F, editorArea, true);
layout.addStandaloneViewPlaceholder(MarkerView.VIEW_ID + ":2", IPageLayout.BOTTOM, 0.6F, editorArea, true);
The problem is that not knowing what the number of views will be, the ratios won't provide equal space to all instances of the view.
Is it somehow possible to adjust the ratios of existing views after adding a new one?
I've also tried having the view class implement ISizeProvider (which I admit I do not have a full grasp of), but haven't managed to achieve what I want with that either:
#Override
public int getSizeFlags(boolean width) {
return width ? 0 : SWT.FILL | SWT.MIN | SWT.MAX;
}
#Override
public int computePreferredSize(boolean width, int availableParallel, int availablePerpendicular, int preferredResult) {
int windowHeight = PlatformUI.getWorkbench().getDisplay().getActiveShell().getBounds().height;
int nrOfViews = Model.getInstance().markerCounter;
return width ? preferredResult : windowHeight / nrOfViews;
}
Is this approach something in the right direction at least?