Skip to content

Commit

Permalink
Merge pull request #1980 from alcomposer/24hourtime
Browse files Browse the repository at this point in the history
Fix 24 hour time OS setting detection for Windows
  • Loading branch information
timothyschoen authored Nov 28, 2024
2 parents 1daeb92 + 6652b9a commit 20343e9
Show file tree
Hide file tree
Showing 16 changed files with 348 additions and 84 deletions.
Binary file modified Resources/Fonts/IconFont.ttf
Binary file not shown.
19 changes: 17 additions & 2 deletions Source/Canvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1647,10 +1647,17 @@ bool Canvas::keyPressed(KeyPress const& key)
return false;
}

void Canvas::deselectAll()
void Canvas::deselectAll(bool broadcastChange)
{
if (!broadcastChange) selectedComponents.removeChangeListener(this);

selectedComponents.deselectAll();
editor->sidebar->hideParameters();

if (!broadcastChange) {
// Add back the listener, but make sure it's added back 'after' the last event on the message queue
MessageManager::callAsync([this](){selectedComponents.addChangeListener(this);});
}
}

void Canvas::hideAllActiveEditors()
Expand Down Expand Up @@ -2631,16 +2638,24 @@ void Canvas::hideSuggestions()
}

// Makes component selected
void Canvas::setSelected(Component* component, bool shouldNowBeSelected, bool updateCommandStatus)
void Canvas::setSelected(Component* component, bool shouldNowBeSelected, bool updateCommandStatus, bool broadcastChange)
{
if (!broadcastChange) { selectedComponents.removeChangeListener(this); }

if (!shouldNowBeSelected) {
selectedComponents.deselect(component);
} else {
selectedComponents.addToSelection(component);
}

if (updateCommandStatus) {
editor->updateCommandStatus();
}

if (!broadcastChange) {
// Add back the listener, but make sure it's added back 'after' the last event on the message queue
MessageManager::callAsync([this](){selectedComponents.addChangeListener(this);});
}
}

SelectedItemSet<WeakReference<Component>>& Canvas::getLassoSelection()
Expand Down
4 changes: 2 additions & 2 deletions Source/Canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ class Canvas : public Component
bool autoscroll(MouseEvent const& e);

// Multi-dragger functions
void deselectAll();
void setSelected(Component* component, bool shouldNowBeSelected, bool updateCommandStatus = true);
void deselectAll(bool broadcastChange = true);
void setSelected(Component* component, bool shouldNowBeSelected, bool updateCommandStatus = true, bool broadcastChange = true);

SelectedItemSet<WeakReference<Component>>& getLassoSelection() override;

Expand Down
165 changes: 125 additions & 40 deletions Source/Components/WelcomePanel.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class WelcomePanel : public Component
nvgFillColor(nvg, NVGComponent::convertColour(findColour(PlugDataColour::panelTextColourId)));
nvgText(nvg, 96, 138, "Recently Opened", NULL);

nvgFontFace(nvg, "plugdata_icon_font");
nvgFontFace(nvg, "icon_font-Regular");
nvgFontSize(nvg, 14);
nvgFillColor(nvg, NVGComponent::convertColour(findColour(PlugDataColour::panelTextColourId).withAlpha(isHoveringClearButton ? 0.6f : 1.0f)));
nvgText(nvg, clearButtonBounds.getCentreX(), clearButtonBounds.getCentreY(), Icons::Clear.toRawUTF8(), NULL);
Expand Down Expand Up @@ -159,7 +159,7 @@ class WelcomePanel : public Component
}

case Open: {
nvgFontFace(nvg, "plugdata_icon_font");
nvgFontFace(nvg, "icon_font-Regular");
nvgFillColor(nvg, bgCol);
nvgFontSize(nvg, 34);
nvgTextAlign(nvg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
Expand Down Expand Up @@ -199,6 +199,9 @@ class WelcomePanel : public Component

void mouseUp(MouseEvent const& e) override
{
if (!getScreenBounds().reduced(12).contains(e.getScreenPosition()))
return;

if (!e.mods.isLeftButtonDown())
return;

Expand All @@ -211,6 +214,7 @@ class WelcomePanel : public Component
bool isFavourited;
std::function<void()> onClick = []() { };
std::function<void(bool)> onFavourite = nullptr;
std::function<void()> onRemove = []() { };

private:
WelcomePanel& parent;
Expand All @@ -223,17 +227,74 @@ class WelcomePanel : public Component
Image thumbnailImageData;
int lastWidth = -1;
int lastHeight = -1;


String creationTimeDescription = String();
String modifiedTimeDescription = String();
String fileSizeDescription = String();

File patchFile;

public:
WelcomePanelTile(WelcomePanel& welcomePanel, ValueTree subTree, String svgImage, Colour iconColour, float scale, bool favourited, Image const& thumbImage = Image())
: parent(welcomePanel)
, isFavourited(favourited)
, snapshotScale(scale)
, thumbnailImageData(thumbImage)
{
patchFile = File(subTree.getProperty("Path").toString());
tileName = patchFile.getFileNameWithoutExtension();

auto is24Hour = OSUtils::is24HourTimeFormat();

auto formatTimeDescription = [is24Hour](const Time& openTime) {
auto diff = Time::getCurrentTime() - openTime;

String date;
auto days = diff.inDays();
if (days < 1)
date = "Today";
else if (days > 1 && days < 2)
date = "Yesterday";
else
date = openTime.toString(true, false);

String time = openTime.toString(false, true, false, is24Hour);

return date + ", " + time;
};

tileSubtitle = formatTimeDescription(Time(static_cast<int64>(subTree.getProperty("Time"))));

auto const fileSize = patchFile.getSize();

if (fileSize < 1024) {
fileSizeDescription = String(fileSize) + " Bytes"; // Less than 1 KiB
} else if (fileSize < 1024 * 1024) {
fileSizeDescription = String(fileSize / 1024.0, 2) + " KiB"; // Between 1 KiB and 1 MiB
} else {
fileSizeDescription = String(fileSize / (1024.0 * 1024.0), 2) + " MiB"; // 1 MiB or more
}

creationTimeDescription = formatTimeDescription(patchFile.getCreationTime());
modifiedTimeDescription = formatTimeDescription(patchFile.getLastModificationTime());

updateGeneratedThumbnailIfNeeded(thumbImage, svgImage, iconColour);
}

WelcomePanelTile(WelcomePanel& welcomePanel, String name, String subtitle, String svgImage, Colour iconColour, float scale, bool favourited, Image const& thumbImage = Image())
: isFavourited(favourited)
, parent(welcomePanel)
: parent(welcomePanel)
, isFavourited(favourited)
, snapshotScale(scale)
, tileName(name)
, tileSubtitle(subtitle)
, thumbnailImageData(thumbImage)
{
if (!thumbImage.isValid()) {
updateGeneratedThumbnailIfNeeded(thumbImage, svgImage, iconColour);
}

void updateGeneratedThumbnailIfNeeded(Image const& thumbnailImage, String& svgImage, Colour iconColour)
{
if (!thumbnailImage.isValid()) {
snapshot = Drawable::createFromImageData(svgImage.toRawUTF8(), svgImage.getNumBytesAsUTF8());
if (snapshot) {
snapshot->replaceColour(Colours::black, iconColour);
Expand All @@ -242,7 +303,47 @@ class WelcomePanel : public Component

resized();
}


void setHovered()
{
isHovered = true;
repaint();
}

void mouseDown(MouseEvent const& e) override {
if (!e.mods.isRightButtonDown())
return;

PopupMenu tileMenu;

tileMenu.addItem(PlatformStrings::getBrowserTip(), [this]() {
if (patchFile.existsAsFile())
patchFile.revealToUser();
});
tileMenu.addSeparator();
tileMenu.addItem(isFavourited ? "Remove from favourites" : "Add to favourites", [this]() {
isFavourited = !isFavourited;
onFavourite(isFavourited);
});
tileMenu.addSeparator();
PopupMenu patchInfoSubMenu;
patchInfoSubMenu.addItem(String("Size: " + fileSizeDescription), false, false, nullptr);
patchInfoSubMenu.addSeparator();
patchInfoSubMenu.addItem(String("Created: " + creationTimeDescription), false, false, nullptr);
patchInfoSubMenu.addItem(String("Modified: " + modifiedTimeDescription), false, false, nullptr);
patchInfoSubMenu.addItem(String("Accessed: " + tileSubtitle), false, false, nullptr);
tileMenu.addSubMenu(String(tileName + ".pd file info"), patchInfoSubMenu, true);
tileMenu.addSeparator();
// TODO: we may want to be clearer about this - that it doesn't delete the file on disk
// Put this at he bottom, so it's not accidentally clicked on
tileMenu.addItem("Remove from recently opened", onRemove);

PopupMenu::Options options;
options.withTargetComponent(this);

tileMenu.showMenuAsync(options);
}

void setSearchQuery(String const& searchQuery)
{
setVisible(tileName.containsIgnoreCase(searchQuery));
Expand Down Expand Up @@ -398,6 +499,11 @@ class WelcomePanel : public Component
if (!e.mods.isLeftButtonDown())
return;

// If the cursor is no longer over the tile, don't trigger the tile
// (Standard behaviour for mouse up on object)
if (!getLocalBounds().reduced(12).contains(e.getPosition()))
return;

if (onFavourite && getHeartIconBounds().contains(e.x, e.y)) {
isFavourited = !isFavourited;
onFavourite(isFavourited);
Expand Down Expand Up @@ -522,7 +628,7 @@ class WelcomePanel : public Component

auto tilesBounds = Rectangle<int>(24, showNewOpenTiles ? 146 : 24, totalWidth + 24, totalHeight + 24);

contentComponent.setBounds(tiles.size() ? tilesBounds : bounds);
contentComponent.setBounds(tiles.size() ? tilesBounds : getLocalBounds());

viewport.setBounce(!tiles.isEmpty());

Expand Down Expand Up @@ -583,24 +689,6 @@ class WelcomePanel : public Component

triggerAsyncUpdate();
}

String getSystemLocalTime(uint64 timestamp) {
StackArray<char, 100> buffer;
std::time_t now = static_cast<std::time_t>(timestamp / 1000);
std::tm* localTime = std::localtime(&now);

// Format the time using the current locale
std::strftime(buffer.data(), buffer.size(), "%X", localTime);

auto result = String::fromUTF8(buffer.data());

// Remove seconds from system time format
auto secondsStart = result.lastIndexOfChar(':');
auto secondsEnd = result.indexOfChar(secondsStart, ' ');
if(secondsEnd < 0) secondsEnd = result.length();

return result.substring(0, secondsStart) + result.substring(secondsEnd);
}

void handleAsyncUpdate() override
{
Expand Down Expand Up @@ -648,21 +736,8 @@ class WelcomePanel : public Component
}
}

auto openTimestamp = static_cast<int64>(subTree.getProperty("Time"));
auto openTime = Time(openTimestamp);
auto diff = Time::getCurrentTime() - openTime;
String date;
if (diff.inDays() == 0)
date = "Today";
else if (diff.inDays() == 1)
date = "Yesterday";
else
date = openTime.toString(true, false);

String time = getSystemLocalTime(openTimestamp);
String timeDescription = date + ", " + time;
auto* tile = recentlyOpenedTiles.add(new WelcomePanelTile(*this, subTree, silhoutteSvg, snapshotColour, 1.0f, favourited, thumbImage));

auto* tile = recentlyOpenedTiles.add(new WelcomePanelTile(*this, patchFile.getFileNameWithoutExtension(), timeDescription, silhoutteSvg, snapshotColour, 1.0f, favourited, thumbImage));
tile->onClick = [this, patchFile]() mutable {
if (patchFile.existsAsFile()) {
editor->pd->autosave->checkForMoreRecentAutosave(patchFile, editor, [this, patchFile]() {
Expand All @@ -683,6 +758,16 @@ class WelcomePanel : public Component
subTree.setProperty("Pinned", shouldBeFavourite, nullptr);
resized();
};
tile->onRemove = [this, path = subTree.getProperty("Path")]() {
auto settingsTree = SettingsFile::getInstance()->getValueTree();
auto recentlyOpenedTree = settingsTree.getChildWithName("RecentlyOpened");
auto subTree = recentlyOpenedTree.getChildWithProperty("Path", path);
recentlyOpenedTree.removeChild(subTree, nullptr);
// Make sure to clear the recent items in the current welcome panel
if (editor->welcomePanel)
editor->welcomePanel->triggerAsyncUpdate();
};

contentComponent.addAndMakeVisible(tile);
}
}
Expand Down
18 changes: 17 additions & 1 deletion Source/Constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ struct Icons {

inline static String const Reorder = "(";
inline static String const Object = ":";
inline static String const ObjectMulti = CharPointer_UTF8("\xc2\xb9");

inline static String const List = "!";
inline static String const Graph = "<";
Expand All @@ -102,7 +103,7 @@ struct Icons {
inline static String const Paste = "1";
inline static String const Duplicate = "2";
inline static String const Cut = "3";

inline static String const PanelExpand = CharPointer_UTF8("\xc3\x8d");
inline static String const PanelContract = CharPointer_UTF8("\xc3\x8c");
inline static String const ItemGrid = " ";
Expand All @@ -118,6 +119,9 @@ struct Icons {

inline static String const Home = CharPointer_UTF8 ("\xc3\x8e");

inline static String const ShowIndex = CharPointer_UTF8("\xc2\xbA");
inline static String const ShowXY = CharPointer_UTF8("\xc2\xbb");

// ================== OBJECT ICONS ==================

// generic
Expand Down Expand Up @@ -426,3 +430,15 @@ enum Align {
VCentre,
VDistribute
};

namespace PlatformStrings {
inline String getBrowserTip() {
#if JUCE_MAC
return "Reveal in Finder";
#elif JUCE_WINDOWS
return "Reveal in Explorer";
#else
return "Reveal in file browser";
#endif
}
}
2 changes: 1 addition & 1 deletion Source/NVGSurface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ void NVGSurface::initialise()
nvgCreateFontMem(nvg, "Inter-Bold", (unsigned char*)BinaryData::InterBold_ttf, BinaryData::InterBold_ttfSize, 0);
nvgCreateFontMem(nvg, "Inter-SemiBold", (unsigned char*)BinaryData::InterSemiBold_ttf, BinaryData::InterSemiBold_ttfSize, 0);
nvgCreateFontMem(nvg, "Inter-Tabular", (unsigned char*)BinaryData::InterTabular_ttf, BinaryData::InterTabular_ttfSize, 0);
nvgCreateFontMem(nvg, "plugdata_icon_font", (unsigned char*)BinaryData::IconFont_ttf, BinaryData::IconFont_ttfSize, 0);
nvgCreateFontMem(nvg, "icon_font-Regular", (unsigned char*)BinaryData::IconFont_ttf, BinaryData::IconFont_ttfSize, 0);

invalidateAll();
}
Expand Down
Loading

0 comments on commit 20343e9

Please sign in to comment.