Fltk Button Call back - c++

For this sub-window I have created a button, but when I click on the button nothing happens. I want to exit the sub-window once I click on the button, but I am not sure how to do that.
void model(Fl_Widget *, void *) {
Fl_Window *head = new Fl_Window(400, 350, "Robot Model: ");
Fl_Input *input = new Fl_Input(200, 0, 100, 30, "Name: ");
Fl_Input *input1 = new Fl_Input(200, 40, 100, 30, "Part-Number: ");
Fl_Input *input2 = new Fl_Input(200, 80, 100, 30, "How much is the Weight: ");
Fl_Input *input3 = new Fl_Input(200, 120, 100, 30, "The Cost: ");
Fl_Input *input4 = new Fl_Input(200, 160, 100, 30, "Brief Description: ");
Fl_Button *enter = new Fl_Button(150, 200, 100, 30, "Enter");
head->show();
}
int main(){
Fl_Window *win = new Fl_Window(600, 500, "Robot Workshop");
Fl_Box *box = new Fl_Box(0, 10, 600, 100, "Welcome to Robot Workshop!");
box->box(FL_UP_BOX);
box->labelsize(36);
box->labelfont(FL_BOLD + FL_ITALIC);
box->labeltype(FL_SHADOW_LABEL);
Fl_Menu_Bar *menu = new Fl_Menu_Bar(0, 0, 600, 25);
menu->add("Exit/Quit", FL_CTRL + 'v', Quit_CB);
menu->add("Project Manager/Robot Part/Head", FL_CTRL + 'h', head);
menu->add("Project Manager/Robot Part/Torso", FL_CTRL + 't', torso);
menu->add("Project Manager/Robot Part/Arm", FL_CTRL + 'a', arm);
menu->add("Project Manager/Robot Part/Battery", FL_CTRL + 'b', battery);
menu->add("Project Manager/Robot Part/Locomotor", FL_CTRL + 'l', locomotor);
menu->add("Project Manager/Robot Model" ,FL_CTRL + 'w', model);
menu->add("Beloved Customer/Browse Catalog", FL_CTRL + 'z', catalog);
menu->add("Beloved Customer/Part Pictures", FL_CTRL + 'v', pic);
menu->add("Manual", FL_CTRL + 'm', manual_window);
win->show();
return(Fl::run());
}

If you want a callback you need to add a callback function. See http://www.fltk.org/doc-1.3/common.html
void xyz_callback(Fl_Widget *w, void *data) {
...
}
You can pass anything you like to data and cast it back to its original type. Then modify your button with
button->callback(xyz_callback, &xyz_data);

Related

Am charts 4 LineSeries legend colors doesn't match graph colors

I have created a series chart using AmCharts version 4.
I have a red line that represents created cases and green line that represent closed cases. However my legend is blue for both lines. How can I get the legend color to fit the graph color?
I added color in the data section.
My code is here:
<script>
am4core.ready(function() {
var chart = am4core.create("chartdiv_cases_created_per_day", am4charts.XYChart);
chart.data = [
{
"x": "Mon 1",
"created_value": 1,
"created_color": am4core.color("red"),
"closed_value": 2,
"closed_color": am4core.color("green")
},
{
"x": "Tue 2",
"created_value": 4,
"created_color": am4core.color("red"),
"closed_value": 2,
"closed_color": am4core.color("green")
},
{
"x": "Wed 3",
"created_value": 3,
"created_color": am4core.color("red"),
"closed_value": 1,
"closed_color": am4core.color("green")
}
];
// Create axes
var categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "x";
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
// Create series
var series1 = chart.series.push(new am4charts.LineSeries());
series1.dataFields.valueY = "created_value";
series1.dataFields.categoryX = "x";
series1.name = "Opprettet";
series1.propertyFields.stroke = "created_color";
series1.propertyFields.fill = "created_color";
series1.strokeWidth = 1;
series1.tooltipText = "Opprettet: {valueY}";
// Create series 2
var series2 = chart.series.push(new am4charts.LineSeries());
series2.dataFields.valueY = "closed_value";
series2.dataFields.categoryX = "x";
series2.name = "Lukket";
series2.propertyFields.stroke = "closed_color";
series2.propertyFields.fill = "closed_color";
series2.tooltipText = "Lukket: {valueY}";
// Legend
chart.legend = new am4charts.Legend();
chart.legend.labels.template.text = "[bold {color}]{name}[/]";
// Tooltips
chart.cursor = new am4charts.XYCursor();
chart.cursor.snapToSeries = series;
chart.cursor.xAxis = valueAxis;
}); // end am4core.ready()
</script>
<div id="chartdiv_cases_created_per_day" style="height: 300px;"></div>
Seems like you're combining data and js-objects. That might be what you want but I would perhaps suggest that you separate them, as it would make it easier that day you need to add data from server.
There is no need to include the color for each point. Most likely you want the same color for all the points in the same series.
That you can achieve like this:
series.stroke = am4core.color(color);
series.fill = am4core.color(color);
You have already named the series in the data as created_value and closed_value so we can easily make a function that adds the data, names the series' and colorize them :)
In which turn you just call
createSeries("created_value", "Created", "red");
createSeries("closed_value", "Closed", "green");
Full code (I'm sure there's more refactoring you could do):
am4core.useTheme(am4themes_animated); // Not needed, but looks cool ;)
// Create chart instance
var chart = am4core.create("chartdiv_cases_created_per_day", am4charts.XYChart);
// Add data
chart.data = [{
"date": new Date(2018, 0, 1),
"created_value": 362,
"closed_value": 699
}, {
"date": new Date(2018, 0, 2),
"created_value": 269,
"closed_value": 450
}, {
"date": new Date(2018, 0, 3),
"created_value": 700,
"closed_value": 358
}, {
"date": new Date(2018, 0, 4),
"created_value": 490,
"closed_value": 367
}, {
"date": new Date(2018, 0, 5),
"created_value": 500,
"closed_value": 485
}, {
"date": new Date(2018, 0, 6),
"created_value": 550,
"closed_value": 354
}, {
"date": new Date(2018, 0, 7),
"created_value": 420,
"closed_value": 350,
}];
// Create axes
var dateAxis = chart.xAxes.push(new am4charts.DateAxis());
dateAxis.renderer.grid.template.location = 0;
dateAxis.renderer.minGridDistance = 30;
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
// Create series
function createSeries(field, name, color) {
var series = chart.series.push(new am4charts.LineSeries());
series.dataFields.valueY = field;
series.dataFields.dateX = "date";
series.name = name;
series.tooltipText = "{dateX}: [b]{valueY}[/]";
series.strokeWidth = 2;
series.stroke = am4core.color(color);
series.fill = am4core.color(color);
// Set up tooltip
series.adapter.add("tooltipText", function(ev) {
var text = "[bold]{dateX}[/]\n"
chart.series.each(function(item) {
text += "[" + item.stroke.hex + "]●[/] " + item.name + ": {" + item.dataFields.valueY + "}\n";
});
return text;
});
series.tooltip.getFillFromObject = false;
series.tooltip.background.fill = am4core.color("#fff");
series.tooltip.label.fill = am4core.color("#00");
var bullet = series.bullets.push(new am4charts.CircleBullet());
bullet.circle.stroke = am4core.color("#fff");
bullet.circle.strokeWidth = 2;
return series;
}
createSeries("created_value", "Åpnet", "red");
createSeries("closed_value", "Lukket", "green");
chart.legend = new am4charts.Legend();
chart.cursor = new am4charts.XYCursor();
chart.cursor.maxTooltipDistance = 0;
<script src="//www.amcharts.com/lib/4/core.js"></script>
<script src="//www.amcharts.com/lib/4/charts.js"></script>
<script src="//www.amcharts.com/lib/4/themes/animated.js"></script>
<div id="chartdiv_cases_created_per_day"></div>

If statement Debug

how I'm going to fix the if-statement on line 31. It just don't want to work. I'm using a source code that enables me to easy create 3D objects. Here's the code:
<script src="http://koda.nu/simple3d.js">
ambientLight("white");
var debug = false;
var player = {x: 0, y: 0, z: 500, item: box(0, 0, 500, 200, 200, 1, "red"), speed: 7};
var ball = {x: 0, y: 0, z: -200, item: sphere(0, 0, -200, 100, "yellow"), xSpeed: 0, ySpeed: 0, zSpeed: -15};
var enemy = {x: 0, y: 0, z: -700, item: box(0, 0, -700, 200, 200, 1, "red"), speed: 7};
box(450, 0, -100, 1, 875, 1200, "blue");
box(-450, 0, -100, 1, 875, 1200, "blue");
box(0, 450, -100, 875, 1, 1200, "blue");
box(0, -450, -100, 875, 1, 1200, "blue");
function update() {
if (keyboard.w && player.y < 350) {
player.item.translateY(player.speed);
player.y += player.speed;
}
if (keyboard.s && player.y > -350) {
player.item.translateY(-player.speed);
player.y -= player.speed;
}
if (keyboard.d && player.x < 350) {
player.item.translateX(player.speed);
player.x += player.speed;
}
if (keyboard.a && player.x > -350) {
player.item.translateX(-player.speed);
player.x -= player.speed;
}
/*(This line just don't want to work ---->)*/ if (ball.z == enemy.z) { ball.zSpeed *= -1; }
if (keyboard.shift && keyboard.y) {
debug = true;
}
ball.x += ball.xSpeed;
ball.item.translateX(ball.xSpeed);
ball.y += ball.ySpeed;
ball.item.translateY(ball.ySpeed);
ball.z += ball.zSpeed;
ball.item.translateZ(ball.zSpeed);
while (debug) {
if (keyboard.up) {
moveCameraZ(-player.speed);
}
if (keyboard.down) {
moveCameraZ(player.speed);
}
if (keyboard.left) {
moveCameraX(-player.speed);
}
if (keyboard.right) {
moveCameraX(player.speed);
}
if (keyboard.shift && keyboard.y) {
debug = True;
}
}
}
</script>
your code is very messy, i think it must be instead of { debug = True; } it must be { debug = False; }

FL_Input into a string

Hello I am new to FLTK and right now I have a very simple program, if you run the program, click create then robot part you will see several options choose one. A new window will open with several FL_Input boxes and one enter button I want to make a callback so that when the user presses enter the text entered into in the FL_Input boxes is saved to a string, for example someone enters Space head into the FL_Input and then that value is assigned to a string. I primarily don't need help with the callback just setting a string equal to a FL_Input. Thank you very much for your help
#include <iostream>
#include <sstream>
#include <stdio.h>
#include <FL/Fl.H>
#include <FL/Fl_Text_Display.H>
#include <FL/fl_draw.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Window.H>
#include <FL/filename.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Slider.H>
#include <string>
#include <FL/Fl_Int_Input.H>
#include <list>
#include <FL/Fl_Color_Chooser.H>
#include <vector>
#include <FL/Fl_Button.H>
#include <FL/Fl_Check_Button.H>
#include <FL/Fl_Tabs.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Menu_Bar.H>
#include <FL/Fl_Output.H>
#include <cstdlib>
using namespace std;
void Change_CB(Fl_Widget *w, void *) {
Fl_Menu_Bar *menu = (Fl_Menu_Bar*)w;
Fl_Menu_Item *p;
// Change submenu name
p = (Fl_Menu_Item*)menu->find_item("Edit/Submenu");
if (p) p->label("New Submenu Name");
// Change item name
p = (Fl_Menu_Item*)menu->find_item("Edit/New Submenu Name/Aaa");
if (p) p->label("New Aaa Name");
}
void Quit_CB(Fl_Widget *, void *) {
exit(0);
}
void head_window(Fl_Widget *, void *) {
Fl_Window *head = new Fl_Window(300, 200, "Head");
Fl_Input *input = new Fl_Input(110, 0, 100, 30, "Name");
Fl_Input *input1 = new Fl_Input(110, 40, 100, 30, "Part-Number");
Fl_Input *input2 = new Fl_Input(110, 80, 100, 30, "Weight");
Fl_Input *input3 = new Fl_Input(110, 120, 100, 30, "Cost");
Fl_Button *enter = new Fl_Button(110, 160, 100, 30, "Enter");
head->show();
}
void torso_window(Fl_Widget *, void *) {
Fl_Window *head = new Fl_Window(350, 250, "Torso");
Fl_Input *input = new Fl_Input(150, 0, 100, 30, "Name");
Fl_Input *input1 = new Fl_Input(150, 40, 100, 30, "Part-Number");
Fl_Input *input2 = new Fl_Input(150, 80, 100, 30, "Weight");
Fl_Input *input3 = new Fl_Input(150, 120, 100, 30, "Cost");
Fl_Input *input4 = new Fl_Input(150, 160, 100, 30, "Battery Compartments");
Fl_Button *enter = new Fl_Button(150, 200, 100, 30, "Enter");
head->show();
}
void locomotor_window(Fl_Widget *, void *) {
Fl_Window *head = new Fl_Window(350, 300, "Locomotor");
Fl_Input *input = new Fl_Input(150, 0, 100, 30, "Name");
Fl_Input *input1 = new Fl_Input(150, 40, 100, 30, "Part-Number");
Fl_Input *input2 = new Fl_Input(150, 80, 100, 30, "Weight");
Fl_Input *input3 = new Fl_Input(150, 120, 100, 30, "Cost");
Fl_Input *input4 = new Fl_Input(150, 160, 100, 30, "Speed(MPH)");
Fl_Input *input5 = new Fl_Input(150, 200, 100, 30, "Power Consumed(W)");
Fl_Button *enter = new Fl_Button(150, 240, 100, 30, "Enter");
head->show();
}
void arm_window(Fl_Widget *, void *) {
Fl_Window *head = new Fl_Window(350, 250, "Arm");
Fl_Input *input = new Fl_Input(150, 0, 100, 30, "Name");
Fl_Input *input1 = new Fl_Input(150, 40, 100, 30, "Part-Number");
Fl_Input *input2 = new Fl_Input(150, 80, 100, 30, "Weight");
Fl_Input *input3 = new Fl_Input(150, 120, 100, 30, "Cost");
Fl_Input *input4 = new Fl_Input(150, 160, 100, 30, "Power Consumed(W)");
Fl_Button *enter = new Fl_Button(150, 200, 100, 30, "Enter");
head->show();
}
void battery_window(Fl_Widget *, void *) {
Fl_Window *head = new Fl_Window(350, 250, "Battery");
Fl_Input *input = new Fl_Input(150, 0, 100, 30, "Name");
Fl_Input *input1 = new Fl_Input(150, 40, 100, 30, "Part-Number");
Fl_Input *input2 = new Fl_Input(150, 80, 100, 30, "Weight");
Fl_Input *input3 = new Fl_Input(150, 120, 100, 30, "Cost");
Fl_Input *input4 = new Fl_Input(150, 160, 100, 30, "Energy Stored");
Fl_Button *enter = new Fl_Button(150, 200, 100, 30, "Enter");
head->show();
}
void manual_window(Fl_Widget *, void *) {
Fl_Window *win = new Fl_Window(400, 275);
Fl_Text_Buffer *buff = new Fl_Text_Buffer();
Fl_Text_Display *disp = new Fl_Text_Display(20, 20, 350 , 250 , "Manual");
disp->buffer(buff);
win->resizable(*disp);
win->show();
buff->text("You may click the file button to open a dropdown\nmenu and you will get a button to exit the window\nor press CTRL + v\n"
"You may click create and you get two options either\nto make a robot part or robot model\n"
"Clicking on robot part that shows the parts you may\ncreate and their associated shortcuts\n"
"If you have any questions click help then click on\nmanual to open the manual\n"
);
win->show();
}
int main() {
Fl_Window *win = new Fl_Window(600, 300, "Robot Shop" );
Fl_Menu_Bar *menu = new Fl_Menu_Bar(0, 0, 600, 25);
menu->add("File/Quit", FL_CTRL + 'v', Quit_CB);
menu->add("Create/Robot Part/Head" , FL_CTRL + 'h' , head_window );
menu->add("Create/Robot Part/Torso" , FL_CTRL + 't' , torso_window);
menu->add("Create/Robot Part/Arm" , FL_CTRL + 'a' , arm_window);
menu->add("Create/Robot Part/Battery" , FL_CTRL + 'b' , battery_window);
menu->add("Create/Robot Part/Locomotor" , FL_CTRL + 'l' , locomotor_window);
menu->add("Create/Robot Model");
menu->add("Help/Manual", FL_CTRL + 'm' , manual_window);
win->show();
return(Fl::run());
}
Sorry this is coming late but i think the below will work.
Fl_Input * inp1; //This is a global declaration
Fl_Button * sav1;
static void sav1_cb(Fl_Button *theButton, void*) // The callback function
{
string Surname = inp1 -> value();
cout << Surname;
}
inp1 = new Fl_Input (170+100, 50, 200, 20,"Surname"); // The input field which must be in a window
sav1 = new Fl_Button (170+310, 50 + 280, 100, 30,"Save"); // The save button
sav1->callback((Fl_Callback*)sav1_cb); //Attaching the callback to the save button
What to note is that the "value()" function is what I use to manipulate the data stored or written in the input field. This is just a sample.
Hope it helps.
You need to store your data somewhere. Suggest something like
enum EData
{
EDHeadWeight,
EDHeadCost,
...
EDMax
};
std::string data[EDMax];
Option 1: Change your Fl_Button (enter) to Fl_Return_Button then set the callback for the button to save all the values. This assumes that when the user presses return, they have entered all the values.
Option 2: If you want to capture enter on each input, use when(FL_WHEN_ENTER_KEY)
Fl_Input *input4 = new Fl_Input(150, 160, 100, 30, "Battery Compartments");
input4->when(FL_WHEN_ENTER_KEY);
input4->callback(grab, &data[EDTorsoBattery]);
...
void grab(Fl_Widget* w, void* param)
{
std::string& rv = *((std::string*)param);
Fl_Input* inp = dynamic_cast<Fl_Input*>(w);
rv = inp->value();
}
The problem here is that it requires you to store inp->value() into a const char* yet constants can't be modified... I am completely confused.

Retrieve dictionary elements based on order

Example creation of Dictionary: Dictionary processes Elements in arbitrary fashion. Hence I get the output in mixed order which doesnt correlate with my list x.
x = [100,2,300,4,75]
dct = {}
for i in x:
dct['lst_%s' % i] = []
for z in range(0,5):
dct['lst_%s' % i].extend((x[z],x[z-1]))
print(dct)
{'lst_300': [100, 75, 2, 100, 300, 2, 4, 300, 75, 4], 'lst_75': [100, 75, 2, 100, 300, 2, 4, 300, 75, 4], 'lst_100': [100, 75, 2, 100, 300, 2, 4, 300, 75, 4], 'lst_2': [100, 75, 2, 100, 300, 2, 4, 300, 75, 4], 'lst_4': [100, 75, 2, 100, 300, 2, 4, 300, 75, 4]}
Using sorted key I do get dictionary headers in order corresponding to my list x but how can I retrieve the elements for the same ?
x = [100,2,300,4,75]
dct = {}
for i in x:
dct['lst_%s' % i] = []
for z in range(0,5):
dct['lst_%s' % i].extend((x[z],x[z-1]))
print(sorted(dct))
['lst_100', 'lst_2', 'lst_300', 'lst_4', 'lst_75']
dict is unordered by definition. If you really want an ordered map, use collections.OrderedDict

Mosync: Why wont this display my Layout

I am delving into Layouts & trying to understand how they work. Is a Layout anything like a JPanel in Java Swing? Ie, where we declare a main panel & add all out widgets to that?
One thing I do not understand is when we create a mobile app, we create a Layout & a Listbox. What is the relationship between those 2 objects?
Does the Layout object contain the Listbox, then we add all the widgets to the listbox?
Or does the Listbox have a Layout defined, then we add the widgets to the Listbox & they aligned according to the Layout
Or do we add all widgets to the layout like in Java Swing?
PS: With my experimentation below, my widgets are not shown? Its just a blank black screen. Why does this happen?
#include <MAUtil/Moblet.h>
#include <MAUI/Layout.h>
#include <MAUI/ListBox.h>
#include <MAUI/Label.h>
#include <MAUI/EditBox.h>
#include <MAUI/Screen.h>
#include <MAUtil/Environment.h>
#include <madmath.h>
#include <conprint.h>
using namespace MAUtil;
using namespace MAUI;
class TemperatureScreen : public Screen //, public PointerListener
{
public:
TemperatureScreen()
{
MAExtent screenDim = maGetScrSize();
Layout* mainLayout = new Layout( 0, 0, EXTENT_X(screenDim), EXTENT_Y(screenDim), NULL, 1, 3 );
ListBox* mainListBox = new ListBox( 0, 0, 100, 200, mainLayout,
ListBox::LBO_VERTICAL, ListBox::LBA_LINEAR,
true );
mainListBox -> setPaddingLeft( 10 );
mainListBox -> setPaddingRight( 10 );
mainListBox -> setPaddingTop( 10 );
mainListBox -> setPaddingBottom( 10 );
mainListBox -> setBackgroundColor( 900 );
mainLayout -> setBackgroundColor( 300 );
Label *celLabel = new Label( 10, 300, 50, 20, mainLayout );
Label *fahLabel = new Label( 10, 300, 50, 20, mainLayout );
EditBox *celEdit = new EditBox( 10, 300, 50, 20, mainLayout );
EditBox *fahEdit = new EditBox( 10, 300, 50, 20, mainLayout );
Label *toCelsiusRb = new Label( 10, 300, 50, 20, mainLayout );
Label *toFahRb = new Label( 10, 300, 50, 20, mainLayout );
Label *convertLabel = new Label( 10, 300, 50, 20, mainLayout );
Label *exitLabel = new Label( 10, 300, 50, 20, mainLayout );
celLabel -> setCaption( "Celcius" );
fahLabel -> setCaption( "Fahrenheit" );
convertLabel -> setCaption( "Convert" );
exitLabel -> setCaption( "Exit" );
/*celLabel -> addPointerListener( this );
fahLabel -> addPointerListener( this );
convertLabel -> addPointerListener( this );
exitLabel -> addPointerListener( this );*/
mainLayout -> add( celLabel );
mainLayout -> add( fahLabel );
mainLayout -> add( convertLabel );
mainLayout -> add( exitLabel );
}
};
class TemperatureMoblet : public Moblet
{
public:
TemperatureMoblet()
{
instance = new TemperatureScreen();
instance -> show();
}
~TemperatureMoblet()
{
delete instance;
}
void keyPressEvent(int keyCode, int nativeCode)
{
// todo: handle key presses
printf( "Blah" );
}
void keyReleaseEvent(int keyCode, int nativeCode)
{
// todo: handle key releases
}
private:
TemperatureScreen *instance;
};
extern "C" int MAMain()
{
Moblet::run(new TemperatureMoblet());
return 0;
};
Try putting an maUpdateScreen() in a timer event or in the key listener, just to see what happens.
If you need more help just get back to me.
You could try the new version 2.6 of mosync at:
http://www.mosync.com/documentation/manualpages/whats-new-mosync-26-pyramid
/Tony