add color settings

This commit is contained in:
Jenny Diomidova 2025-12-09 22:44:06 +01:00
parent eff33f57a1
commit d30dfa5d57
9 changed files with 210 additions and 111 deletions

View File

@ -26,7 +26,9 @@
"watchface": true "watchface": true
}, },
"messageKeys": [ "messageKeys": [
"dummy" "BACKGROUND_COLOR",
"DIGIT_COLOR",
"FRAME_COLOR"
], ],
"capabilities": [ "configurable" ], "capabilities": [ "configurable" ],
"resources": { "resources": {

View File

@ -4,95 +4,97 @@
using namespace Pebble; using namespace Pebble;
// TODO move this to pebble-cpp // TODO move this to pebble-cpp
bool operator==(const GColor8& lhs, const GColor8& rhs) { return lhs.argb == rhs.argb; } bool operator==(const GColor& lhs, const GColor& rhs) { return gcolor_equal(lhs, rhs); }
bool operator!=(const GColor8& lhs, const GColor8& rhs) { return lhs.argb != rhs.argb; } bool operator!=(const GColor& lhs, const GColor& rhs) { return !gcolor_equal(lhs, rhs); }
namespace { namespace bitmaps {
GOwnedBitmap digitsBitmap; namespace {
GOwnedBitmap digitBitmaps[10]; GOwnedBitmap digitsBitmap;
GOwnedBitmap frameBitmap; GOwnedBitmap digitBitmaps[10];
GOwnedBitmap frameBitmap;
GColor* digitColor; GColor* digitColor;
GColor* frameColor; GColor* frameColor;
int get_palette_size(GBitmapBase& bitmap){ int GetPaletteSize(GBitmapBase& bitmap){
switch (bitmap.GetFormat()) { switch (bitmap.GetFormat()) {
case GBitmapFormat1BitPalette: return 2; case GBitmapFormat1BitPalette: return 2;
case GBitmapFormat2BitPalette: return 4; case GBitmapFormat2BitPalette: return 4;
case GBitmapFormat4BitPalette: return 16; case GBitmapFormat4BitPalette: return 16;
default: return 0; default: return 0;
}
}
GColor* find_color(GBitmapBase& bitmap, GColor color) {
GColor* palette = bitmap.GetPalette();
if (palette == nullptr) {
ERROR("Palette is null");
return nullptr;
}
int paletteSize = get_palette_size(bitmap);
if (paletteSize == 0) {
ERROR("Expected GBitmapFormat[124]BitPalette, got: %d", digitsBitmap.GetFormat());
return nullptr;
}
for (int i = 0; i < paletteSize; i++) {
if (palette[i] == color) {
DEBUG("Found color 0x%02X at index %d", color, i);
return &palette[i];
} }
} }
ERROR("Color 0x%02X not found in the palette", color);
return nullptr;
}
}
void init_bitmaps() { GColor* FindColor(GBitmapBase& bitmap, GColor color) {
digitsBitmap = GOwnedBitmap::CreateWithResource(RESOURCE_ID_DIGITS); GColor* palette = bitmap.GetPalette();
auto size = digitsBitmap.GetBounds().size; if (palette == nullptr) {
uint16_t w = size.w / 10; ERROR("Palette is null");
uint16_t h = size.h; return nullptr;
for (int i = 0; i < 10; i++) { }
digitBitmaps[i] = GOwnedBitmap::CreateSubBitmap(digitsBitmap, Pebble::GRect(i * w, 0, w, h));
int paletteSize = GetPaletteSize(bitmap);
if (paletteSize == 0) {
ERROR("Expected GBitmapFormat[124]BitPalette, got: %d", digitsBitmap.GetFormat());
return nullptr;
}
for (int i = 0; i < paletteSize; i++) {
if (palette[i] == color) {
DEBUG("Found color 0x%02X at index %d", color, i);
return &palette[i];
}
}
ERROR("Color 0x%02X not found in the palette", color);
return nullptr;
}
} }
frameBitmap = GOwnedBitmap::CreateWithResource(RESOURCE_ID_FRAME); void Init() {
digitsBitmap = GOwnedBitmap::CreateWithResource(RESOURCE_ID_DIGITS);
auto size = digitsBitmap.GetBounds().size;
uint16_t w = size.w / 10;
uint16_t h = size.h;
for (int i = 0; i < 10; i++) {
digitBitmaps[i] = GOwnedBitmap::CreateSubBitmap(digitsBitmap, Pebble::GRect(i * w, 0, w, h));
}
digitColor = find_color(digitsBitmap, GColorBlack); frameBitmap = GOwnedBitmap::CreateWithResource(RESOURCE_ID_FRAME);
frameColor = find_color(frameBitmap, GColorBlack);
}
void deinit_bitmaps() { digitColor = FindColor(digitsBitmap, GColorBlack);
for (int i = 0; i < 10; i++) { frameColor = FindColor(frameBitmap, GColorBlack);
digitBitmaps[i] = GOwnedBitmap();
} }
digitsBitmap = GOwnedBitmap();
frameBitmap = GOwnedBitmap();
digitColor = nullptr;
frameColor = nullptr;
}
GBitmapBase& get_digit_bitmap(uint16_t digit) {return digitBitmaps[digit];} void DeInit() {
GBitmapBase& get_frame_bitmap() {return frameBitmap;} for (int i = 0; i < 10; i++) {
digitBitmaps[i] = GOwnedBitmap();
}
void set_digit_color(GColor color) { digitsBitmap = GOwnedBitmap();
if (digitColor != nullptr) *digitColor = color; frameBitmap = GOwnedBitmap();
} digitColor = nullptr;
void set_frame_color(GColor color) { frameColor = nullptr;
if (frameColor != nullptr) *frameColor = color;
}
void print_palette(GBitmapBase& bitmap) {
int paletteSize = get_palette_size(bitmap);
if (paletteSize == 0) {
ERROR("Expected GBitmapFormat[124]BitPalette, got: %d", digitsBitmap.GetFormat());
return;
} }
DEBUG("%d colors:", paletteSize);
GColor8* palette = bitmap.GetPalette(); GBitmapBase& GetDigitBitmap(uint16_t digit) {return digitBitmaps[digit];}
for (int i = 0; i < paletteSize; i++) { GBitmapBase& GetFrameBitmap() {return frameBitmap;}
DEBUG("* 0x%02X = argb(%d,%d,%d,%d)", palette[i].argb, palette[i].a, palette[i].r, palette[i].g, palette[i].b);
void SetDigitColor(GColor color) {
if (digitColor != nullptr) *digitColor = color;
}
void SetFrameColor(GColor color) {
if (frameColor != nullptr) *frameColor = color;
}
void PrintPalette(GBitmapBase& bitmap) {
int paletteSize = GetPaletteSize(bitmap);
if (paletteSize == 0) {
ERROR("Expected GBitmapFormat[124]BitPalette, got: %d", digitsBitmap.GetFormat());
return;
}
DEBUG("%d colors:", paletteSize);
GColor* palette = bitmap.GetPalette();
for (int i = 0; i < paletteSize; i++) {
DEBUG("* 0x%02X = argb(%d,%d,%d,%d)", palette[i].argb, palette[i].a, palette[i].r, palette[i].g, palette[i].b);
}
} }
} }

View File

@ -2,10 +2,12 @@
#include <pebble-cpp/pebble.hpp> #include <pebble-cpp/pebble.hpp>
void init_bitmaps(); namespace bitmaps {
void deinit_bitmaps(); void Init();
Pebble::GBitmapBase& get_digit_bitmap(uint16_t digit); void DeInit();
Pebble::GBitmapBase& get_frame_bitmap(); Pebble::GBitmapBase& GetDigitBitmap(uint16_t digit);
void set_digit_color(GColor color); Pebble::GBitmapBase& GetFrameBitmap();
void set_frame_color(GColor color); void SetDigitColor(GColor color);
void print_palette(Pebble::GBitmapBase& bitmap); void SetFrameColor(GColor color);
void PrintPalette(Pebble::GBitmapBase& bitmap);
}

View File

@ -1,12 +1,12 @@
#include "digit_layer.hpp" #include "digit_layer.hpp"
#include "bitmaps.hpp"
#include <@rebble/sdk-c-utils/macros.h> #include <@rebble/sdk-c-utils/macros.h>
#include "bitmaps.hpp"
using namespace Pebble; using namespace Pebble;
namespace { namespace {
void draw_digit(const Pebble::GContext& ctx, const Pebble::GRect& bounds, const uint16_t digit) { void draw_digit(const Pebble::GContext& ctx, const Pebble::GRect& bounds, const uint16_t digit) {
Pebble::GBitmapBase& bitmap = get_digit_bitmap(digit); Pebble::GBitmapBase& bitmap = bitmaps::GetDigitBitmap(digit);
auto rect = bitmap.GetBounds(); auto rect = bitmap.GetBounds();
rect.Align(bounds, GAlignCenter, false); rect.Align(bounds, GAlignCenter, false);
ctx.DrawBitmapInRect(bitmap, rect); ctx.DrawBitmapInRect(bitmap, rect);

View File

@ -3,6 +3,7 @@
#include "pebble_bitmap_layer.hpp" #include "pebble_bitmap_layer.hpp"
#include "digit_layer.hpp" #include "digit_layer.hpp"
#include "bitmaps.hpp" #include "bitmaps.hpp"
#include "settings.hpp"
using namespace Pebble; using namespace Pebble;
@ -13,8 +14,6 @@ class MainWindow : public AppWindow, public TickTimer {
Pebble::BitmapLayer frameLayer; Pebble::BitmapLayer frameLayer;
protected: protected:
void OnLoad() { void OnLoad() {
init_bitmaps();
auto bounds = this->GetBounds(); auto bounds = this->GetBounds();
int16_t w2 = bounds.size.w / 2; int16_t w2 = bounds.size.w / 2;
int16_t h = bounds.size.h; int16_t h = bounds.size.h;
@ -32,12 +31,7 @@ protected:
this->AddChild(this->digitLayers[i]); this->AddChild(this->digitLayers[i]);
} }
// print_palette(get_digit_bitmap(0)); this->frameLayer.SetBitmap(bitmaps::GetFrameBitmap());
// print_palette(get_frame_bitmap());
// set_frame_color(GColorPictonBlue);
// print_palette(get_digit_bitmap(0));
// print_palette(get_frame_bitmap());
this->frameLayer.SetBitmap(get_frame_bitmap());
this->frameLayer.SetFrame(bounds); this->frameLayer.SetFrame(bounds);
this->frameLayer.SetCompositingMode(GCompOpSet); this->frameLayer.SetCompositingMode(GCompOpSet);
this->AddChild(this->frameLayer); this->AddChild(this->frameLayer);
@ -48,14 +42,6 @@ protected:
TickTimerStart(MINUTE_UNIT); TickTimerStart(MINUTE_UNIT);
#endif #endif
UpdateTime(false); UpdateTime(false);
this->SetBackgroundColor(GColorBlack);
set_digit_color(GColorVividCerulean);
set_frame_color(GColorPictonBlue);
}
void OnUnload() {
deinit_bitmaps();
} }
void UpdateTime(bool animate=true) { void UpdateTime(bool animate=true) {
@ -78,9 +64,35 @@ protected:
} }
}; };
namespace {
void ApplySettings() {
Pebble::Window window = window_stack_get_top_window();
window.SetBackgroundColor(settings::GetBackgroundColor());
window.MarkDirty();
bitmaps::SetDigitColor(settings::GetDigitColor());
bitmaps::SetFrameColor(settings::GetFrameColor());
}
void HandleMsg(DictionaryIterator *iter, void *context) {
settings::HandleMsg(iter);
ApplySettings();
}
}
MAIN { MAIN {
bitmaps::Init();
settings::Load();
app_message_register_inbox_received(HandleMsg);
app_message_open(64, 64); // inbox, outbox
MainWindow window; MainWindow window;
window.StackPush(true); window.StackPush(true);
ApplySettings();
app_event_loop(); app_event_loop();
bitmaps::DeInit();
return 0; return 0;
} }

44
src/c/settings.cpp Normal file
View File

@ -0,0 +1,44 @@
#include "settings.hpp"
// Built-in GColorFromRGBA doesn't seem to work in C++11 :(
#undef GColorFromRGBA
GColor8 GColorFromRGBA(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) {
GColor8 res;
res.a = alpha >> 6;
res.r = red >> 6;
res.g = green >> 6;
res.b = blue >> 6;
return res;
}
namespace settings {
namespace {
GColor backgroundColor = GColorWhite;
GColor digitColor = GColorBlack;
GColor frameColor = GColorBlack;
}
void Save() {
persist_write_data(MESSAGE_KEY_BACKGROUND_COLOR, &backgroundColor, sizeof(GColor));
persist_write_data(MESSAGE_KEY_DIGIT_COLOR, &digitColor, sizeof(GColor));
persist_write_data(MESSAGE_KEY_FRAME_COLOR, &frameColor, sizeof(GColor));
}
void Load() {
persist_read_data(MESSAGE_KEY_BACKGROUND_COLOR, &backgroundColor, sizeof(GColor));
persist_read_data(MESSAGE_KEY_DIGIT_COLOR, &digitColor, sizeof(GColor));
persist_read_data(MESSAGE_KEY_FRAME_COLOR, &frameColor, sizeof(GColor));
}
void HandleMsg(DictionaryIterator *iter) {
if (auto tuple = dict_find(iter, MESSAGE_KEY_BACKGROUND_COLOR)) backgroundColor = GColorFromHEX(tuple->value->int32);
if (auto tuple = dict_find(iter, MESSAGE_KEY_DIGIT_COLOR)) digitColor = GColorFromHEX(tuple->value->int32);
if (auto tuple = dict_find(iter, MESSAGE_KEY_FRAME_COLOR)) frameColor = GColorFromHEX(tuple->value->int32);
Save();
}
GColor GetBackgroundColor() {return backgroundColor; }
GColor GetDigitColor() {return digitColor; }
GColor GetFrameColor() {return frameColor; }
}

12
src/c/settings.hpp Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#include <pebble-cpp/pebble.hpp>
namespace settings {
void Save();
void Load();
void HandleMsg(DictionaryIterator *iter);
GColor GetBackgroundColor();
GColor GetDigitColor();
GColor GetFrameColor();
}

View File

@ -1,10 +1,36 @@
module.exports = [ module.exports = [
{ {
"type": "heading", type: "section",
"defaultValue": "Example Header Item" items: [
{
type: "heading",
defaultValue: "Colors",
},
{
label: "Background Color",
messageKey: "BACKGROUND_COLOR",
type: "color",
defaultValue: "#FFFFFF",
allowGray: true,
},
{
label: "Digit Color",
messageKey: "DIGIT_COLOR",
type: "color",
defaultValue: "#000000",
allowGray: true,
},
{
label: "Frame Color",
messageKey: "FRAME_COLOR",
type: "color",
defaultValue: "#00000",
allowGray: true,
},
]
}, },
{ {
"type": "text", type: "submit",
"defaultValue": "Example text item." defaultValue: "Save Settings",
} },
]; ];

View File

@ -1,4 +1,3 @@
var Clay = require('pebble-clay'); var Clay = require('pebble-clay');
var clayConfig = require('./config'); var clayConfig = require('./config');
var clay = new Clay(clayConfig); var clay = new Clay(clayConfig);
console.log('Loaded clay!');