kopia lustrzana https://github.com/jamescoxon/dl-fldigi
616 wiersze
12 KiB
C++
616 wiersze
12 KiB
C++
// ----------------------------------------------------------------------------
|
|
// Copyright (C) 2014
|
|
// David Freese, W1HKJ
|
|
//
|
|
// This file is part of fldigi
|
|
//
|
|
// fldigi is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// fldigi is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#include <config.h>
|
|
|
|
#include <cstring>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
|
|
#include <FL/Fl.H>
|
|
#include <FL/Fl_Pixmap.H>
|
|
|
|
#include "pixmaps.h"
|
|
#include "calendar.h"
|
|
|
|
void popcal_cb (Fl_Widget *v, long d);
|
|
|
|
static void fl_calendar_button_cb (Fl_Button *a, void *b)
|
|
{
|
|
long j=0;
|
|
Fl_Calendar *c = (Fl_Calendar *)b;
|
|
Fl_Button *sb;
|
|
int numdays = c->daysinmonth () + 1;
|
|
for (int i=1; i < numdays; i++) {
|
|
sb = c->day_button(i);
|
|
sb->color (52);
|
|
if (a == sb) {
|
|
c->Day (i);
|
|
j = i;
|
|
sb->color (sb->selection_color());
|
|
if (c->target) {
|
|
((Fl_Input2 *)(c->target))->value(c->szDate(c->calfmt));
|
|
(c->target)->redraw();
|
|
}
|
|
}
|
|
}
|
|
c->redraw();
|
|
c->do_callback(c, j);
|
|
}
|
|
|
|
void
|
|
Fl_Calendar_Base::setTarget (Fl_Widget *tgt)
|
|
{
|
|
target = tgt;
|
|
}
|
|
|
|
Fl_Calendar_Base::Fl_Calendar_Base (int x, int y, int w, int h,
|
|
const char *l) : Fl_Group (x, y, w, h, l), Date ()
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i<(7*6); i++)
|
|
{
|
|
days[i] = new Fl_Button ((w/7)*(i%7) + x,
|
|
(h/6)*(i/7) + y,
|
|
(w/7),
|
|
(h/6));
|
|
days[i]->down_box (FL_THIN_DOWN_BOX);
|
|
days[i]->labelsize (10);
|
|
days[i]->box (FL_THIN_UP_BOX);
|
|
days[i]->color (52);
|
|
days[i]->callback ((Fl_Callback*)&fl_calendar_button_cb, (void *)this);
|
|
}
|
|
calfmt = 0;
|
|
}
|
|
|
|
void Fl_Calendar_Base::csize (int cx, int cy, int cw, int ch)
|
|
{
|
|
int i;
|
|
for (i = 0; i<(7*6); i++)
|
|
{
|
|
days[i]->resize ((cw/7)*(i%7) + cx,
|
|
(ch/6)*(i/7) + cy,
|
|
(cw/7),
|
|
(ch/6));
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
Fl_Calendar_Base::update ()
|
|
{
|
|
int dow = dayofweek (Year(), Month(), 1);
|
|
int dim = daysinmonth (Month(), isleapyear (Year()));
|
|
int i;
|
|
|
|
for (i=0; i<dow; i++)
|
|
{
|
|
days[i]->hide ();
|
|
}
|
|
|
|
for (i=(dim+dow); i<(6*7); i++)
|
|
{
|
|
days[i]->hide ();
|
|
}
|
|
|
|
for (i=dow; i<(dim+dow); i++)
|
|
{
|
|
char t[8];
|
|
snprintf (t, sizeof(t), "%d", (i-dow+1));
|
|
days[i]->label (strdup(t));
|
|
days[i]->color (52);
|
|
if ((i-dow+1) == Day())
|
|
days[i]->color (selection_color());
|
|
days[i]->show ();
|
|
}
|
|
}
|
|
|
|
Fl_Button *
|
|
Fl_Calendar_Base::day_button (int i)
|
|
{
|
|
if ((i > 0) && (i <= daysinmonth ()))
|
|
return days[i + dayofweek (Year(), Month(), 1) - 1];
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
fl_calendar_prv_month_cb (Fl_Button *, void *b)
|
|
{
|
|
Fl_Calendar *c = (Fl_Calendar *)b;
|
|
c->previous_month ();
|
|
c->do_callback(c, (long)0);
|
|
}
|
|
|
|
static void
|
|
fl_calendar_nxt_month_cb (Fl_Button *, void *b)
|
|
{
|
|
Fl_Calendar *c = (Fl_Calendar *)b;
|
|
c->next_month ();
|
|
c->do_callback(c, (long)0);
|
|
}
|
|
|
|
static void
|
|
fl_calendar_prv_year_cb (Fl_Button *, void *b)
|
|
{
|
|
Fl_Calendar *c = (Fl_Calendar *)b;
|
|
c->previous_year ();
|
|
c->do_callback(c, (long)0);
|
|
}
|
|
|
|
static void
|
|
fl_calendar_nxt_year_cb (Fl_Button *, void *b)
|
|
{
|
|
Fl_Calendar *c = (Fl_Calendar *)b;
|
|
c->next_year ();
|
|
c->do_callback(c, (long)0);
|
|
}
|
|
|
|
Fl_Calendar::Fl_Calendar (int x, int y, int w, int h,
|
|
const char *l) : Fl_Calendar_Base (x, y, w, h, l)
|
|
{
|
|
int i, bw;
|
|
for (i = 0; i<7; i++) {
|
|
// weekdays[i] = new Fl_Button ((w/7)*(i%7) + x,
|
|
weekdays[i] = new Fl_Box ((w/7)*(i%7) + x,
|
|
(h/8)*((i/7)+1) + y,
|
|
(w/7),
|
|
(h/8));
|
|
weekdays[i]->box (FL_THIN_UP_BOX);
|
|
weekdays[i]->labelsize (10);
|
|
weekdays[i]->color (52);
|
|
}
|
|
|
|
weekdays[SUNDAY]->label ("S");
|
|
weekdays[MONDAY]->label ("M");
|
|
weekdays[TUESDAY]->label ("T");
|
|
weekdays[WEDNESDAY]->label ("W");
|
|
weekdays[THURSDAY]->label ("T");
|
|
weekdays[FRIDAY]->label ("F");
|
|
weekdays[SATURDAY]->label ("S");
|
|
|
|
bw = w/10 < 16 ? 16 : w/10;
|
|
prv_year = new Fl_Button (x, y, bw, (h/8), "@<<");
|
|
prv_year->box (FL_THIN_UP_BOX);
|
|
prv_year->labeltype (FL_SYMBOL_LABEL);
|
|
prv_year->labelsize (10);
|
|
prv_year->down_box (FL_THIN_DOWN_BOX);
|
|
prv_year->callback ((Fl_Callback*)&fl_calendar_prv_year_cb, (void *)this);
|
|
|
|
prv_month = new Fl_Button (x + bw, y, bw, (h/8), "@<");
|
|
prv_month->box (FL_THIN_UP_BOX);
|
|
prv_month->labeltype (FL_SYMBOL_LABEL);
|
|
prv_month->labelsize (10);
|
|
prv_month->down_box (FL_THIN_DOWN_BOX);
|
|
prv_month->callback ((Fl_Callback*)&fl_calendar_prv_month_cb, (void *)this);
|
|
|
|
nxt_month = new Fl_Button (x + w - 2*bw, y, bw, (h/8), "@>");
|
|
nxt_month->box (FL_THIN_UP_BOX);
|
|
nxt_month->labeltype (FL_SYMBOL_LABEL);
|
|
nxt_month->labelsize (10);
|
|
nxt_month->down_box (FL_THIN_DOWN_BOX);
|
|
nxt_month->callback ((Fl_Callback*)&fl_calendar_nxt_month_cb, (void *)this);
|
|
|
|
nxt_year = new Fl_Button (x + w - bw, y, bw, (h/8), "@>>");
|
|
nxt_year->box (FL_THIN_UP_BOX);
|
|
nxt_year->labeltype (FL_SYMBOL_LABEL);
|
|
nxt_year->labelsize (10);
|
|
nxt_year->down_box (FL_THIN_DOWN_BOX);
|
|
nxt_year->callback ((Fl_Callback*)&fl_calendar_nxt_year_cb, (void *)this);
|
|
|
|
// caption = new Fl_Button (x + (w/10)*2, y, (6*w/10), (h/8));
|
|
caption = new Fl_Box (x + 2*bw, y, w - 4*bw, (h/8));
|
|
caption->box (FL_THIN_UP_BOX);
|
|
caption->labeltype (FL_SYMBOL_LABEL);
|
|
caption->labelfont (1);
|
|
if (bw < 20)
|
|
caption->labelsize (9);
|
|
else
|
|
caption->labelsize (11);
|
|
// caption->down_box (FL_THIN_DOWN_BOX);
|
|
|
|
Fl_Calendar_Base::csize (x, y + (2*h/8), w, (6*h/8));
|
|
|
|
target = 0;
|
|
|
|
update ();
|
|
}
|
|
|
|
void
|
|
Fl_Calendar::csize (int cx, int cy, int cw, int ch)
|
|
{
|
|
int i;
|
|
for (i = 0; i<7; i++)
|
|
{
|
|
// weekdays[i] = new Fl_Button ((cw/7)*(i%7) + cx,
|
|
weekdays[i] = new Fl_Box ((cw/7)*(i%7) + cx,
|
|
(ch/8)*((i/7)+1) + cy,
|
|
(cw/7),
|
|
(ch/8));
|
|
}
|
|
|
|
prv_month->resize (cx + (cw/10), cy, (cw/10), (ch/8));
|
|
nxt_month->resize (cx + (cw/10)*8, cy, (cw/10), (ch/8));
|
|
prv_year->resize (cx, cy, (cw/10), (ch/8));
|
|
nxt_year->resize (cx + (cw/10)*9, cy, (cw/10), (ch/8));
|
|
caption->resize (cx + (cw/10)*2, cy, (cw/10)*6, (ch/8));
|
|
|
|
Fl_Calendar_Base::csize (cx, cy + (2*ch/8), cw, (6*ch/8));
|
|
}
|
|
|
|
void
|
|
Fl_Calendar::update ()
|
|
{
|
|
int dow = dayofweek (Year(), Month(), 1);
|
|
int dim = daysinmonth (Month(), isleapyear (Year()));
|
|
int i;
|
|
|
|
for (i=dow; i<(dim+dow); i++)
|
|
{
|
|
char t[8];
|
|
snprintf (t, sizeof(t), "%d", (i-dow+1));
|
|
days[i]->label (strdup(t));
|
|
}
|
|
|
|
char tmp[32];
|
|
snprintf (tmp, sizeof(tmp), "%s %d", month_name[Month()-1], Year());
|
|
Fl_Calendar_Base::update ();
|
|
if (caption->label ())
|
|
free ((void *) caption->label ());
|
|
caption->label (strdup(tmp));
|
|
redraw ();
|
|
}
|
|
|
|
void Fl_Calendar::today ()
|
|
{
|
|
Date::today();
|
|
update ();
|
|
}
|
|
|
|
void Fl_Calendar::previous_month ()
|
|
{
|
|
Date::previous_month();
|
|
update ();
|
|
}
|
|
|
|
void
|
|
Fl_Calendar::next_month ()
|
|
{
|
|
Date::next_month();
|
|
update ();
|
|
}
|
|
|
|
void
|
|
Fl_Calendar::previous_year ()
|
|
{
|
|
Date::previous_year();
|
|
update ();
|
|
}
|
|
|
|
void Fl_Calendar::next_year ()
|
|
{
|
|
Date::next_year();
|
|
update ();
|
|
}
|
|
|
|
void Fl_Calendar::setDate(int m, int d, int y)
|
|
{
|
|
Date::setDate(m,d,y);
|
|
}
|
|
|
|
int
|
|
Fl_Calendar::handle (int event)
|
|
{
|
|
int m, d, y, o, md;
|
|
|
|
switch (event)
|
|
{
|
|
case FL_FOCUS:
|
|
case FL_UNFOCUS:
|
|
return 1;
|
|
|
|
case FL_KEYBOARD:
|
|
m = Month ();
|
|
d = Day ();
|
|
y = Year ();
|
|
switch(Fl::event_key ())
|
|
{
|
|
case FL_Enter:
|
|
do_callback(this, d);
|
|
return 1;
|
|
break;
|
|
case FL_Up:
|
|
o = -7;
|
|
break;
|
|
case FL_Down:
|
|
o = 7;
|
|
break;
|
|
case FL_Right:
|
|
o = 1;
|
|
break;
|
|
case FL_Left:
|
|
o = -1;
|
|
break;
|
|
case FL_Page_Up:
|
|
previous_month ();
|
|
return 1;
|
|
case FL_Page_Down:
|
|
next_month ();
|
|
return 1;
|
|
default:
|
|
return Fl_Group::handle (event);
|
|
}
|
|
if (datevalid (y, m, d + o))
|
|
setDate (m, d + o, y);
|
|
else
|
|
{
|
|
if (o < 0)
|
|
{
|
|
previous_month ();
|
|
m = Month ();
|
|
y = Year ();
|
|
md = daysinmonth (m, isleapyear (y));
|
|
d = d + o + md;
|
|
setDate (m, d, y);
|
|
}
|
|
else
|
|
{
|
|
md = daysinmonth (m, isleapyear (y));
|
|
next_month ();
|
|
m = Month ();
|
|
y = Year ();
|
|
d = d + o - md;
|
|
setDate (m, d, y);
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
return Fl_Group::handle (event);
|
|
}
|
|
|
|
|
|
// Popup Calendar class
|
|
|
|
Fl_PopCal::Fl_PopCal (int X, int Y, int W, int H, Fl_Input2 * tgt)
|
|
: Fl_Window (X, Y, W, H, "")
|
|
{
|
|
target = tgt;
|
|
clear_border();
|
|
box(FL_UP_BOX);
|
|
// popcal = new Fl_Calendar(2, 2);
|
|
popcal = new Fl_Calendar(2, 2, W-4, H-4);
|
|
popcal->callback ( (Fl_Callback*)popcal_cb);
|
|
end();
|
|
}
|
|
|
|
|
|
Fl_PopCal::~Fl_PopCal ()
|
|
{
|
|
}
|
|
|
|
void Fl_PopCal::popcalfmt (int i)
|
|
{
|
|
popcalfmt_ = i;
|
|
}
|
|
|
|
int Fl_PopCal::popcalfmt ()
|
|
{
|
|
return popcalfmt_;
|
|
}
|
|
|
|
void Fl_PopCal::setDate (int m, int d, int y)
|
|
{
|
|
popcal->setDate (m,d,y);
|
|
popcal->update();
|
|
}
|
|
|
|
int Fl_PopCal::handle(int event)
|
|
{
|
|
int ex = Fl::event_x_root(),
|
|
ey = Fl::event_y_root();
|
|
if (event == FL_PUSH) {
|
|
if ( ex < x() || ex > (x() + w()) ||
|
|
ey < y() || ey > (y() + h()) ) {
|
|
pophide();
|
|
return 1;
|
|
}
|
|
}
|
|
if (Fl_Group::handle(event)) return 1;
|
|
return 0;
|
|
}
|
|
|
|
void Fl_PopCal::popposition (int x, int y)
|
|
{
|
|
position (x, y);
|
|
}
|
|
|
|
void Fl_PopCal::popshow ()
|
|
{
|
|
show ();
|
|
Fl::grab(this);
|
|
}
|
|
|
|
void Fl_PopCal::pophide ()
|
|
{
|
|
hide ();
|
|
Fl::release();
|
|
}
|
|
|
|
void Fl_PopCal::popcal_cb_i (Fl_Widget *v, long d)
|
|
{
|
|
int ey = Fl::event_y_root();
|
|
Fl_PopCal *me = (Fl_PopCal *)(v->parent());
|
|
Fl_Input2 *tgt = me->target;
|
|
if (ey > me->y() + 40) {
|
|
if (d && tgt)
|
|
tgt->value (((Fl_Calendar *)v)->szDate (me->popcalfmt_));
|
|
me->pophide();
|
|
}
|
|
return;
|
|
}
|
|
|
|
void popcal_cb (Fl_Widget *v, long d)
|
|
{
|
|
((Fl_PopCal *)(v))->popcal_cb_i (v, d);
|
|
return;
|
|
}
|
|
|
|
void
|
|
Fl_DateInput::fl_popcal()
|
|
{
|
|
Fl_Widget *who = this, *parent;
|
|
int xpos = who->x(), ypos = who->h() + who->y();
|
|
int w = who->w(), h;
|
|
int m = 0, d = 0, y = 0;
|
|
|
|
w = w < 140 ? 140 : w;
|
|
w = w - (w % 7);
|
|
h = 8*(w/7);
|
|
w += 4; h += 4;
|
|
parent = who;
|
|
while (parent) {
|
|
who = parent;
|
|
parent = parent->parent();
|
|
if (parent == 0) {
|
|
xpos += who->x();
|
|
ypos += who->y();
|
|
}
|
|
}
|
|
if (!Cal)
|
|
// Cal = new Fl_PopCal(xpos, ypos, 7*20+4, 8*20+4, Input);
|
|
Cal = new Fl_PopCal(xpos, ypos, w, h, Input);
|
|
else
|
|
Cal->popposition(xpos, ypos);
|
|
|
|
if (popcalfmt_ < 3) {
|
|
switch (popcalfmt_) {
|
|
case 0:
|
|
case 1:
|
|
sscanf(Input->value(), "%d/%d/%d", &m, &d, &y);
|
|
break;
|
|
case 2:
|
|
default:
|
|
sscanf(Input->value(),"%4d%2d%2d", &y, &m, &d);
|
|
break;
|
|
}
|
|
if (y < 10) y+=2000;
|
|
if (y < 100) y+=1900;
|
|
Cal->setDate (m,d,y);
|
|
}
|
|
Cal->popcalfmt (popcalfmt_);
|
|
|
|
Cal->popshow();
|
|
return;
|
|
}
|
|
|
|
void btnDateInput_cb (Fl_Widget *v, void *d)
|
|
{
|
|
((Fl_DateInput *)(v->parent()))->fl_popcal ();
|
|
return;
|
|
}
|
|
|
|
|
|
Fl_DateInput::Fl_DateInput (int X,int Y,int W,int H, const char *L)
|
|
: Fl_Group (X, Y, W, H, 0)
|
|
{
|
|
Btn = new Fl_Button (X + W - H, Y, H, H);
|
|
(new Fl_Pixmap (time_icon))->label (Btn);
|
|
Btn->callback ((Fl_Callback *)btnDateInput_cb, 0);
|
|
Input = new Fl_Input2 (X, Y, W-H, H, L);
|
|
|
|
popcalfmt_ = 0;
|
|
Cal = 0;
|
|
end();
|
|
}
|
|
|
|
void Fl_DateInput::align (Fl_Align how)
|
|
{
|
|
Input->align(how);
|
|
}
|
|
|
|
// DateInput value is contained in the Input widget
|
|
|
|
void Fl_DateInput::value( const char *s )
|
|
{
|
|
Input->value (s);
|
|
}
|
|
|
|
const char *Fl_DateInput::value()
|
|
{
|
|
return (Input->value ());
|
|
}
|
|
|
|
|
|
void Fl_DateInput::textfont(int tf)
|
|
{
|
|
Input->textfont (tf);
|
|
}
|
|
|
|
void Fl_DateInput::textsize(int sz)
|
|
{
|
|
Input->textsize (sz);
|
|
}
|
|
|
|
void Fl_DateInput::textcolor(Fl_Color c)
|
|
{
|
|
Input->textcolor(c);
|
|
}
|
|
|
|
void Fl_DateInput::color(Fl_Color c)
|
|
{
|
|
Input->color(c);
|
|
}
|
|
|
|
void Fl_DateInput::labelfont(int fnt)
|
|
{
|
|
Input->labelfont(fnt);
|
|
}
|
|
|
|
void Fl_DateInput::labelsize(int size)
|
|
{
|
|
Input->labelsize(size);
|
|
}
|
|
|
|
void Fl_DateInput::labelcolor(int clr)
|
|
{
|
|
Input->labelcolor(clr);
|
|
}
|
|
|
|
void Fl_DateInput::format (int fmt)
|
|
{
|
|
switch (fmt) {
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
popcalfmt_ = fmt;
|
|
break;
|
|
default :
|
|
popcalfmt_ = 0;
|
|
}
|
|
}
|
|
|
|
void Fl_DateInput::take_focus() {
|
|
Input->take_focus();
|
|
}
|