FLTK logo

Re: [fltk/fltk] possible incoherence in Fl_Tree_Item drawing (Issue #298)

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 All Forums  |  Back to fltk.issues  ]
 
Previous Message ]New Message | Reply ]Next Message ]

Re: [fltk/fltk] possible incoherence in Fl_Tree_Item drawing (Issue #298) Mohammed Alyousef Nov 29, 2021  
 

In rust this could be translated to something like:

use fltk::{enums::*, prelude::*, *};
use std::cell::RefCell;
use std::rc::Rc;

const eye_open_xpm: &[&str] = &[
    "18 12 5 1",
    "       c None",
    ".      c #5B90E9",
    "+      c #87ABE5",
    "@      c #B2D2FD",
    "#      c #F5FEFE",
    "########@@########",
    "#####@++++++@#####",
    "####+........+####",
    "###+...+##+...+###",
    "#@....+####+....@#",
    "#+....@#@@#@....+#",
    "@.....##++##.....@",
    "#+....@####@....+#",
    "##+....####....+##",
    "###@....++....@###",
    "####@+......+@####",
    "######@@++@@######",
];

const eye_close_xpm: &[&str] = &[
    "18 12 5 1",
    "       c None",
    ".      c #5B90E9",
    "+      c #87ABE5",
    "@      c #B2D2FD",
    "#      c #F5FEFE",
    "########@@####+.@#",
    "#####@++++++@..+##",
    "####+.....+@..+###",
    "###+...+##@...+@##",
    "#@....+##@.+....@#",
    "#+....@#+.++....+#",
    "@.....#+.+##.....@",
    "#+...@+.+##@....+#",
    "##+.@..+###....+##",
    "###@....++....@###",
    "##@.++......+@####",
    "#@.@##@@++@@######",
];

lazy_static::lazy_static! {
    static ref eye_open_pixmap: image::Pixmap = image::Pixmap::new(eye_open_xpm).unwrap();
    static ref eye_close_pixmap: image::Pixmap = image::Pixmap::new(eye_close_xpm).unwrap();
}

struct MyTreeItem {
    item: tree::TreeItem,
    xpm1: Rc<RefCell<image::Pixmap>>,
    xp1: Rc<RefCell<[i32; 4]>>,
    xpm2: Rc<RefCell<image::Pixmap>>,
    xp2: Rc<RefCell<[i32; 4]>>,
}

impl MyTreeItem {
    pub fn event_inside(v: [i32; 4]) -> bool {
        app::event_inside(v[0], v[1], v[2], v[3])
    }
    pub fn new(tree: &tree::Tree, name: &str) -> Self {
        let mut item = tree::TreeItem::new(tree, name);
        item.set_label_size(14);
        let xpm1 = Rc::from(RefCell::from(eye_open_pixmap.clone()));
        let xpm2 = Rc::from(RefCell::from(eye_close_pixmap.clone()));
        let xp1 = Rc::from(RefCell::from([0i32; 4]));
        let xp2 = Rc::from(RefCell::from([0i32; 4]));
        item.draw_item_content({
            let xpm1 = xpm1.clone();
            let xpm2 = xpm2.clone();
            let xp1 = xp1.clone();
            let xp2 = xp2.clone();
            move |item, render| {
                let mut xpm1 = xpm1.borrow_mut();
                let mut xpm2 = xpm2.borrow_mut();
                let mut xp1 = xp1.borrow_mut();
                let mut xp2 = xp2.borrow_mut();
                //    Show the date and time as two small strings
                //    one on top of the other in a single item.
                //
                // Our item's label dimensions
                let mut X = item.label_x();
                let Y = item.label_y();
                let W = item.label_w();
                let H = item.label_h();
                // Render background + label
                if render {
                    draw::set_draw_color(Color::White);
                    draw::draw_rectf(X, Y, W, H);
                    draw::set_draw_color(Color::Black);
                    if item.label().is_some() {
                        draw::draw_text2(&item.label().unwrap(), X, Y, W, H, Align::Left);
                    }
                }
                let mut lw = 0;
                if item.label().is_some() {
                    let sz = draw::measure(&item.label().unwrap(), true);
                    lw = sz.0;
                }
                X += lw + 8;
                {
                    // Calculate xpm's xywh draw area
                    let yoff = (H - xpm1.h()) / 2;
                    xp1[0] = X;
                    xp1[1] = Y + yoff;
                    xp1[2] = xpm1.w();
                    xp1[3] = xpm1.h();
                    X = item.label_x() + item.label_w() - xpm2.w() - 10; // right justify xpm2 w/10 pix margin
                    xp2[0] = X;
                    xp2[1] = Y + yoff;
                    xp2[2] = xpm2.w();
                    xp2[3] = xpm2.h();
                    X += xpm2.w();
                    // Draw the xpms
                    if render {
                        xpm1.draw(xp1[0], xp1[1], xp1[2], xp1[3]);
                        xpm2.draw(xp2[0], xp2[1], xp2[2], xp2[3]);
                    }
                }
                return X;
            }
        });
        Self {
            item,
            xpm1,
            xp1,
            xpm2,
            xp2,
        }
    }
    fn handle(&mut self) {
        let mut xpm1 = self.xpm1.borrow_mut();
        let mut xpm2 = self.xpm2.borrow_mut();
        let xp1 = self.xp1.borrow_mut();
        let xp2 = self.xp2.borrow_mut();
        if Self::event_inside(*xp1) {
            *xpm1 = if *xpm1 == *eye_open_pixmap {
                eye_close_pixmap.clone()
            } else {
                eye_open_pixmap.clone()
            };
        }
        if Self::event_inside(*xp2) {
            *xpm2 = if *xpm2 == *eye_close_pixmap {
                eye_open_pixmap.clone()
            } else {
                eye_close_pixmap.clone()
            };
        }
    }
}

fn main() {
    let a = app::App::default();
    let mut win = window::Window::default().with_size(350, 400);
    win.begin();
    {
        // Create the tree
        let mut tree = tree::Tree::new(0, 0, win.w(), win.h(), None);
        tree.set_trigger(CallbackTrigger::Changed | CallbackTrigger::Release); // when to invoke callback
        tree.set_item_reselect_mode(tree::TreeItemReselectMode::Always); // callback even when reselected

        // Add some items
        tree.add("Flintstones/Fred");
        tree.add("Flintstones/Wilma");
        tree.add("Flintstones/Pebbles");

        // Add a few custom items
        {
            let mut i = MyTreeItem::new(&tree, "MyItem-001");
            tree.add_item("Custom Item/MyItem-001", &i.item);
            tree.set_callback(move |tree| {
                if let Some(item) = tree.callback_item() {
                    if let Some(label) = item.label() {
                        if label.contains("MyItem") {
                            match tree.callback_reason() {
                                tree::TreeReason::Selected | tree::TreeReason::Reselected => {
                                    MyTreeItem::handle(&mut i);
                                }
                                _ => (),
                            }
                        }
                    }
                }
            });
        }
        tree.add("Superjail/Alice");
        tree.add("Superjail/Jailbot");
    }
    win.end();
    win.make_resizable(true);
    win.show();
    a.run().unwrap();
}

It needs a way to distringuish items in the callback, currently casting would require unsafe, I'll probably add some equality/compare function for tree items.


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.

Direct Link to Message ]
 
     
Previous Message ]New Message | Reply ]Next Message ]
 
 

Comments are owned by the poster. All other content is copyright 1998-2024 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.