Skip to content

Commit

Permalink
Add a calendar button to every DateBox
Browse files Browse the repository at this point in the history
Showing the calendar window and setting the date on the DateBox is all
handled by the CalendarButton.

CalendarMenuWindow.cpp was lifted from the Calendar app and Deskbar.
  • Loading branch information
humdingerb committed Jun 10, 2024
1 parent 061b45a commit 7369d7b
Show file tree
Hide file tree
Showing 14 changed files with 578 additions and 160 deletions.
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ SRCS = \
src/Budget.cpp \
src/BudgetReport.cpp \
src/BudgetWindow.cpp \
src/CalendarButton.cpp\
src/CalendarMenuWindow.cpp \
src/CashFlowReport.cpp \
src/Category.cpp \
src/CategoryBox.cpp \
Expand Down Expand Up @@ -118,7 +120,7 @@ RSRCS = \
# - if your library does not follow the standard library naming scheme,
# you need to specify the path to the library and it's name.
# (e.g. for mylib.a, specify "mylib.a" or "path/mylib.a")
LIBS = be tracker localestub translation sqlite3 columnlistview $(STDCPPLIBS)
LIBS = be tracker shared localestub translation sqlite3 columnlistview $(STDCPPLIBS)

# Specify additional paths to directories following the standard libXXX.so
# or libXXX.a naming scheme. You can specify full paths or paths relative
Expand All @@ -130,7 +132,9 @@ LIBPATHS =
# Additional paths to look for system headers. These use the form
# "#include <header>". Directories that contain the files in SRCS are
# NOT auto-included here.
SYSTEM_INCLUDE_PATHS = $(shell findpaths -e B_FIND_PATH_HEADERS_DIRECTORY private/interface)
SYSTEM_INCLUDE_PATHS = \
$(shell findpaths -e B_FIND_PATH_HEADERS_DIRECTORY private/interface) \
$(shell findpaths -e B_FIND_PATH_HEADERS_DIRECTORY private/shared)

# Additional paths paths to look for local headers. These use the form
# #include "header". Directories that contain the files in SRCS are
Expand Down
87 changes: 87 additions & 0 deletions src/CalendarButton.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#include "CalendarButton.h"
#include "CalendarMenuWindow.h"
#include "Database.h"

#include <DateFormat.h>

enum {
M_SHOW_CALENDER,
M_SET_DATE
};


CalendarButton::CalendarButton(DateBox* datebox)
: BButton("calenderbutton", "📅", new BMessage(M_SHOW_CALENDER)),
fDateBox(datebox)
{
float height;
fDateBox->GetPreferredSize(NULL, &height);
BSize size(height + 2, height);
SetExplicitSize(size);
}


void
CalendarButton::AttachedToWindow(void)
{
SetTarget(this);
}


void
CalendarButton::MessageReceived(BMessage* msg)
{
switch (msg->what) {
case M_SHOW_CALENDER:
{
ShowPopUpCalendar();
break;
}
case M_SET_DATE:
{
int32 day, month, year;
BString date;
msg->FindInt32("day", &day);
msg->FindInt32("month", &month);
msg->FindInt32("year", &year);
date << day << "." << month << "." << year;
fDateBox->SetText(date);
fDateBox->Validate();
break;
}
default:
{
BButton::MessageReceived(msg);
}
}
}



void
CalendarButton::ShowPopUpCalendar()
{
if (fCalendarWindow.IsValid()) {
BMessage activate(B_SET_PROPERTY);
activate.AddSpecifier("Active");
activate.AddBool("data", true);

if (fCalendarWindow.SendMessage(&activate) == B_OK)
return;
}

BDate date = fDateBox->GetDate();
BMessage* invocationMessage = new BMessage(M_SET_DATE);
BPoint where = Bounds().LeftTop();
ConvertToScreen(&where);

CalendarMenuWindow* window = new CalendarMenuWindow(this, where);
window->SetDate(date);
window->SetInvocationMessage(invocationMessage);
window->SetDate(date);
fCalendarWindow = BMessenger(window);
window->Show();

window->MoveBy(Bounds().Width() / 2, window->Bounds().Height() * -1.5);
window->MoveOnScreen(B_MOVE_IF_PARTIALLY_OFFSCREEN);
}
26 changes: 26 additions & 0 deletions src/CalendarButton.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef CALENDARBUTTON_H
#define CALENDARBUTTON_H


#include <Button.h>
#include <SupportDefs.h>

#include "DateBox.h"


class CalendarButton : public BButton {
public:
CalendarButton(DateBox* box);

void AttachedToWindow(void);
virtual void MessageReceived(BMessage* message);

private:
void ShowPopUpCalendar();

DateBox* fDateBox;
BMessenger fCalendarWindow;

};

#endif // CALENDARBUTTON_H
253 changes: 253 additions & 0 deletions src/CalendarMenuWindow.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
/*
* Copyight 2017 Akshay Agarwal, [email protected]
* Copyright 2008 Karsten Heimrich, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/


#include "CalendarMenuWindow.h"

#include <Button.h>
#include <CalendarView.h>
#include <DateFormat.h>
#include <GridLayoutBuilder.h>
#include <GroupLayout.h>
#include <GroupLayoutBuilder.h>
#include <GroupView.h>
#include <Locale.h>
#include <Screen.h>
#include <SpaceLayoutItem.h>
#include <String.h>
#include <StringView.h>


using BPrivate::BCalendarView;


// #pragma mark - FlatButton


class FlatButton : public BButton
{
public:
FlatButton(const BString& label, uint32 what)
:
BButton(label.String(), new BMessage(what))
{
}
virtual ~FlatButton() {}

virtual void Draw(BRect updateRect);
};


void
FlatButton::Draw(BRect updateRect)
{
updateRect = Bounds();
rgb_color highColor = HighColor();

SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
FillRect(updateRect);

font_height fh;
GetFontHeight(&fh);

const char* label = Label();
const float stringWidth = StringWidth(label);
const float x = (updateRect.right - stringWidth) / 2.0f;
const float labelY = updateRect.top
+ ((updateRect.Height() - fh.ascent - fh.descent) / 2.0f) + fh.ascent
+ 1.0f;

SetHighColor(highColor);
DrawString(label, BPoint(x, labelY));

if (IsFocus()) {
SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
StrokeRect(updateRect);
}
}


// #pragma mark - CalendarMenuWindow


CalendarMenuWindow::CalendarMenuWindow(BHandler* handler, BPoint where)
:
BWindow(BRect(0.0, 0.0, 100.0, 130.0), "", B_BORDERED_WINDOW,
B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_CLOSE_ON_ESCAPE
| B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE),
fYearLabel(NULL),
fMonthLabel(NULL),
fHandler(handler),
fInvocationMessage(NULL),
fCalendarView(NULL),
fSuppressFirstClose(true)
{
SetFeel(B_FLOATING_ALL_WINDOW_FEEL);

RemoveShortcut('H', B_COMMAND_KEY | B_CONTROL_KEY);
AddShortcut('W', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED));

fYearLabel = new BStringView("year", "");
fMonthLabel = new BStringView("month", "");

fCalendarView = new BCalendarView(Bounds(), "calendar", B_FOLLOW_ALL);
fCalendarView->SetInvocationMessage(new BMessage(kInvokationMessage));

BGroupLayout* layout = new BGroupLayout(B_HORIZONTAL);
SetLayout(layout);

float width, height;
fMonthLabel->GetPreferredSize(&width, &height);

BGridLayout* gridLayout = BGridLayoutBuilder(5.0)
.Add(_SetupButton("-", kMonthDownMessage, height), 0, 0)
.Add(fMonthLabel, 1, 0)
.Add(_SetupButton("+", kMonthUpMessage, height), 2, 0)
.Add(BSpaceLayoutItem::CreateGlue(), 3, 0)
.Add(_SetupButton("-", kYearDownMessage, height), 4, 0)
.Add(fYearLabel, 5, 0)
.Add(_SetupButton("+", kYearUpMessage, height), 6, 0)
.SetInsets(5.0, 0.0, 5.0, 0.0);
gridLayout->SetMinColumnWidth(1, be_plain_font->StringWidth("September"));

BGroupView* groupView = new BGroupView(B_VERTICAL, 10.0);
BView* view = BGroupLayoutBuilder(B_VERTICAL, 5.0)
.Add(gridLayout->View())
.Add(fCalendarView)
.SetInsets(5.0, 5.0, 5.0, 5.0)
.TopView();
groupView->AddChild(view);
AddChild(groupView);

MoveTo(where);
}


CalendarMenuWindow::~CalendarMenuWindow()
{
SetInvocationMessage(NULL);
}


void
CalendarMenuWindow::Show()
{
fCalendarView->MakeFocus(true);
BWindow::Show();
}


void
CalendarMenuWindow::WindowActivated(bool active)
{
if (active)
return;

if (mouse_mode() != B_FOCUS_FOLLOWS_MOUSE) {
if (!active)
PostMessage(B_QUIT_REQUESTED);
} else {
if (fSuppressFirstClose && !active) {
fSuppressFirstClose = false;
return;
}

if (!fSuppressFirstClose && !active)
PostMessage(B_QUIT_REQUESTED);
}
}


void
CalendarMenuWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
case kInvokationMessage:
{
int32 day, month, year;
message->FindInt32("day", &day);
message->FindInt32("month", &month);
message->FindInt32("year", &year);
BDate date = BDate(year, month, day);
_UpdateDate(date);

BMessenger msgr(fHandler);
fInvocationMessage->AddInt32("day", day);
fInvocationMessage->AddInt32("month", month);
fInvocationMessage->AddInt32("year", year);
msgr.SendMessage(fInvocationMessage);

PostMessage(B_QUIT_REQUESTED);
break;
}

case kMonthDownMessage:
case kMonthUpMessage:
{
BDate date = fCalendarView->Date();
date.AddMonths(kMonthDownMessage == message->what ? -1 : 1);
_UpdateDate(date);
break;
}

case kYearDownMessage:
case kYearUpMessage:
{
BDate date = fCalendarView->Date();
date.AddYears(kYearDownMessage == message->what ? -1 : 1);
_UpdateDate(date);
break;
}

default:
BWindow::MessageReceived(message);
break;
}
}


void
CalendarMenuWindow::SetInvocationMessage(BMessage* message)
{
delete fInvocationMessage;
fInvocationMessage = message;
}


void
CalendarMenuWindow::SetDate(const BDate& date)
{
_UpdateDate(date);
}


void
CalendarMenuWindow::_UpdateDate(const BDate& date)
{
if (!date.IsValid())
return;

fCalendarView->SetDate(date);

BString yearString;
BString monthString;

yearString << date.Year();
fYearLabel->SetText(yearString);

BDateFormat().GetMonthName(date.Month(), monthString);
fMonthLabel->SetText(monthString);
}


BButton*
CalendarMenuWindow::_SetupButton(const char* label, uint32 what, float height)
{
FlatButton* button = new FlatButton(label, what);
button->SetExplicitMinSize(BSize(height, height));

return button;
}
Loading

0 comments on commit 7369d7b

Please sign in to comment.