ui/winui/icons.cpp

Mon, 23 Sep 2024 23:22:27 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Mon, 23 Sep 2024 23:22:27 +0200
branch
newapi
changeset 309
02c95df91de1
parent 218
d06e7e8e53e1
child 373
2eede3d98aba
permissions
-rw-r--r--

add headerbar toggle button (GTK)

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2017 Olaf Wintermann. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "pch.h"

#include "icons.h"

#include <stdlib.h>
#include <string.h>

#include "util.h"

#include <Windows.h>
#include <Shellapi.h>


using namespace winrt;
using namespace Microsoft::UI::Xaml;
using namespace Microsoft::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Interop;
using namespace winrt::Windows::Foundation;
using namespace winrt::Microsoft::UI::Xaml::Controls::Primitives;
using namespace winrt::Microsoft::UI::Xaml::Media::Imaging;
//using namespace Windows::Storage::Streams;

static UiIcon* sys_folder_icon16;
static UiIcon* sys_file_icon16;

static UiIcon* sys_folder_icon32;
static UiIcon* sys_file_icon32;

std::unordered_map<std::string, Symbol> ui_symbol_icons = {
	{"Accept", Symbol::Accept },
	{"Account", Symbol::Account },
	{"Add", Symbol::Add },
	{"AddFriend", Symbol::AddFriend },
	{"Admin", Symbol::Admin },
	{"AlignCenter", Symbol::AlignCenter },
	{"AlignLeft", Symbol::AlignLeft },
	{"AlignRight", Symbol::AlignRight },
	{"AllApps", Symbol::AllApps },
	{"Attach", Symbol::Attach },
	{"AttachCamera", Symbol::AttachCamera },
	{"Audio", Symbol::Audio },
	{"Back", Symbol::Back },
	{"BackToWindow", Symbol::BackToWindow },
	{"BlockContact", Symbol::BlockContact },
	{"Bold", Symbol::Bold },
	{"Bookmarks", Symbol::Bookmarks },
	{"BrowsePhotos", Symbol::BrowsePhotos },
	{"Bullets", Symbol::Bullets },
	{"Calculator", Symbol::Calculator },
	{"Calendar", Symbol::Calendar },
	{"CalendarDay", Symbol::CalendarDay },
	{"CalendarReply", Symbol::CalendarReply },
	{"CalendarWeek", Symbol::CalendarWeek },
	{"Camera", Symbol::Camera },
	{"Cancel", Symbol::Cancel },
	{"Caption", Symbol::Caption },
	{"CellPhone", Symbol::CellPhone },
	{"Character", Symbol::Character },
	{"Clear", Symbol::Clear },
	{"ClearSelection", Symbol::ClearSelection },
	{"Clock", Symbol::Clock },
	{"ClosedCaption", Symbol::ClosedCaption },
	{"ClosePane", Symbol::ClosePane },
	{"Comment", Symbol::Comment },
	{"Contact", Symbol::Contact },
	{"Contact2", Symbol::Contact2 },
	{"ContactInfo", Symbol::ContactInfo },
	{"ContactPresence", Symbol::ContactPresence },
	{"Copy", Symbol::Copy },
	{"Crop", Symbol::Crop },
	{"Cut", Symbol::Cut },
	{"Delete", Symbol::Delete },
	{"Directions", Symbol::Directions },
	{"DisableUpdates", Symbol::DisableUpdates },
	{"DisconnectDrive", Symbol::DisconnectDrive },
	{"Dislike", Symbol::Dislike },
	{"DockBottom", Symbol::DockBottom },
	{"DockLeft", Symbol::DockLeft },
	{"DockRight", Symbol::DockRight },
	{"Document", Symbol::Document },
	{"Download", Symbol::Download },
	{"Edit", Symbol::Edit },
	{"Emoji", Symbol::Emoji },
	{"Emoji2", Symbol::Emoji2 },
	{"Favorite", Symbol::Favorite },
	{"Filter", Symbol::Filter },
	{"Find", Symbol::Find },
	{"Flag", Symbol::Flag },
	{"Folder", Symbol::Folder },
	{"Font", Symbol::Font },
	{"FontColor", Symbol::FontColor },
	{"FontDecrease", Symbol::FontDecrease },
	{"FontIncrease", Symbol::FontIncrease },
	{"FontSize", Symbol::FontSize },
	{"Forward", Symbol::Forward },
	{"FourBars", Symbol::FourBars },
	{"FullScreen", Symbol::FullScreen },
	{"GlobalNavigationButton", Symbol::GlobalNavigationButton },
	{"Globe", Symbol::Globe },
	{"Go", Symbol::Go },
	{"GoToStart", Symbol::GoToStart },
	{"GoToToday", Symbol::GoToToday },
	{"HangUp", Symbol::HangUp },
	{"Help", Symbol::Help },
	{"HideBcc", Symbol::HideBcc },
	{"Highlight", Symbol::Highlight },
	{"Home", Symbol::Home },
	{"Import", Symbol::Import },
	{"ImportAll", Symbol::ImportAll },
	{"Important", Symbol::Important },
	{"Italic", Symbol::Italic },
	{"Keyboard", Symbol::Keyboard },
	{"LeaveChat", Symbol::LeaveChat },
	{"Library", Symbol::Library },
	{"Like", Symbol::Like },
	{"LikeDislike", Symbol::LikeDislike },
	{"Link", Symbol::Link },
	{"List", Symbol::List },
	{"Mail", Symbol::Mail },
	{"MailFilled", Symbol::MailFilled },
	{"MailForward", Symbol::MailForward },
	{"MailReply", Symbol::MailReply },
	{"MailReplyAll", Symbol::MailReplyAll },
	{"Manage", Symbol::Manage },
	{"Map", Symbol::Map },
	{"MapDrive", Symbol::MapDrive },
	{"MapPin", Symbol::MapPin },
	{"Memo", Symbol::Memo },
	{"Message", Symbol::Message },
	{"Microphone", Symbol::Microphone },
	{"More", Symbol::More },
	{"MoveToFolder", Symbol::MoveToFolder },
	{"MusicInfo", Symbol::MusicInfo },
	{"Mute", Symbol::Mute },
	{"NewFolder", Symbol::NewFolder },
	{"NewWindow", Symbol::NewWindow },
	{"Next", Symbol::Next },
	{"OneBar", Symbol::OneBar },
	{"OpenFile", Symbol::OpenFile },
	{"OpenLocal", Symbol::OpenLocal },
	{"OpenPane", Symbol::OpenPane },
	{"OpenWith", Symbol::OpenWith },
	{"Orientation", Symbol::Orientation },
	{"OtherUser", Symbol::OtherUser },
	{"OutlineStar", Symbol::OutlineStar },
	{"Page", Symbol::Page },
	{"Page2", Symbol::Page2 },
	{"Paste", Symbol::Paste },
	{"Pause", Symbol::Pause },
	{"People", Symbol::People },
	{"Permissions", Symbol::Permissions },
	{"Phone", Symbol::Phone },
	{"PhoneBook", Symbol::PhoneBook },
	{"Pictures", Symbol::Pictures },
	{"Pin", Symbol::Pin },
	{"Placeholder", Symbol::Placeholder },
	{"Play", Symbol::Play },
	{"PostUpdate", Symbol::PostUpdate },
	{"Preview", Symbol::Preview },
	{"PreviewLink", Symbol::PreviewLink },
	{"Previous", Symbol::Previous },
	{"Print", Symbol::Print },
	{"Priority", Symbol::Priority },
	{"ProtectedDocument", Symbol::ProtectedDocument },
	{"Read", Symbol::Read },
	{"Redo", Symbol::Redo },
	{"Refresh", Symbol::Refresh },
	{"Remote", Symbol::Remote },
	{"Remove", Symbol::Remove },
	{"Rename", Symbol::Rename },
	{"Repair", Symbol::Repair },
	{"RepeatAll", Symbol::RepeatAll },
	{"RepeatOne", Symbol::RepeatOne },
	{"ReportHacked", Symbol::ReportHacked },
	{"ReShare", Symbol::ReShare },
	{"Rotate", Symbol::Rotate },
	{"RotateCamera", Symbol::RotateCamera },
	{"Save", Symbol::Save },
	{"SaveLocal", Symbol::SaveLocal },
	{"Scan", Symbol::Scan },
	{"SelectAll", Symbol::SelectAll },
	{"Send", Symbol::Send },
	{"SetLockScreen", Symbol::SetLockScreen },
	{"SetTile", Symbol::SetTile },
	{"Setting", Symbol::Setting },
	{"Share", Symbol::Share },
	{"Shop", Symbol::Shop },
	{"ShowBcc", Symbol::ShowBcc },
	{"ShowResults", Symbol::ShowResults },
	{"Shuffle", Symbol::Shuffle },
	{"SlideShow", Symbol::SlideShow },
	{"SolidStar", Symbol::SolidStar },
	{"Sort", Symbol::Sort },
	{"Stop", Symbol::Stop },
	{"StopSlideShow", Symbol::StopSlideShow },
	{"Street", Symbol::Street },
	{"Switch", Symbol::Switch },
	{"SwitchApps", Symbol::SwitchApps },
	{"Sync", Symbol::Sync },
	{"SyncFolder", Symbol::SyncFolder },
	{"Tag", Symbol::Tag },
	{"Target", Symbol::Target },
	{"ThreeBars", Symbol::ThreeBars },
	{"TouchPointer", Symbol::TouchPointer },
	{"Trim", Symbol::Trim },
	{"TwoBars", Symbol::TwoBars },
	{"TwoPage", Symbol::TwoPage },
	{"Underline", Symbol::Underline },
	{"Undo", Symbol::Undo },
	{"UnFavorite", Symbol::UnFavorite },
	{"UnPin", Symbol::UnPin },
	{"UnSyncFolder", Symbol::UnSyncFolder },
	{"Up", Symbol::Up },
	{"Upload", Symbol::Upload },
	{"Video", Symbol::Video },
	{"VideoChat", Symbol::VideoChat },
	{"View", Symbol::View },
	{"ViewAll", Symbol::ViewAll },
	{"Volume", Symbol::Volume },
	{"WebCam", Symbol::WebCam },
	{"World", Symbol::World },
	{"XboxOneConsole", Symbol::XboxOneConsole },
	{"ZeroBars", Symbol::ZeroBars },
	{"Zoom", Symbol::Zoom },
	{"ZoomIn", Symbol::ZoomIn },
	{"ZoomOut", Symbol::ZoomOut }
};

winrt::Microsoft::UI::Xaml::Controls::IconElement ui_get_icon(const char* name) {
	if (ui_symbol_icons.find(name) == ui_symbol_icons.end()) {
		SymbolIcon no_icon = { nullptr };
		return no_icon;
	}

	Symbol symbol = ui_symbol_icons[name];
	SymbolIcon icon = SymbolIcon(symbol);
	return icon;
}


// symbol icon implementation
UiSymbolIcon::UiSymbolIcon(winrt::Microsoft::UI::Xaml::Controls::Symbol sym) {
	symbol = sym;
}

UiSymbolIcon::~UiSymbolIcon() {
	
}

winrt::Microsoft::UI::Xaml::Controls::IconElement UiSymbolIcon::getIcon() {
	return SymbolIcon(symbol);
}

// image icon implementation
UiImageIcon::UiImageIcon(const char* uristr) {
	wchar_t* wuri = str2wstr(uristr, nullptr);
	Windows::Foundation::Uri uri{ wuri };
	this->uri = uri;
	free(wuri);
}

UiImageIcon::~UiImageIcon() {

}

winrt::Microsoft::UI::Xaml::Controls::IconElement UiImageIcon::getIcon() {
	BitmapIcon icon = BitmapIcon();
	icon.UriSource(uri);
	ImageIcon img = ImageIcon();
	img.Source();
	return icon;
}

// bitmap icon implementation
UiBitmapIcon::UiBitmapIcon(winrt::Microsoft::UI::Xaml::Media::Imaging::BitmapSource bitmap) {
	this->bitmap = bitmap;
}

UiBitmapIcon::~UiBitmapIcon() {

}

winrt::Microsoft::UI::Xaml::Controls::IconElement UiBitmapIcon::getIcon() {
	ImageIcon icon = ImageIcon();
	icon.Source(bitmap);
	return icon;
}

UIEXPORT UiIcon* ui_icon(const char* name, size_t size) {
	Symbol symbol = ui_symbol_icons[name];
	UiSymbolIcon* icon = new UiSymbolIcon(symbol);
	return icon;
}


UIEXPORT UiIcon* ui_imageicon(const char* file) {
	return new UiImageIcon(file);
}

UIEXPORT void ui_icon_free(UiIcon* icon) {
	delete icon;
}


struct __declspec(uuid("905a0fef-bc53-11df-8c49-001e4fc686da")) IBufferByteAccess : ::IUnknown
{
	virtual HRESULT __stdcall Buffer(uint8_t** value) = 0;
};



winrt::Microsoft::UI::Xaml::Media::Imaging::WriteableBitmap ui_dllicon2bitmap(const char* dll, int iconindex, bool large) {
	WriteableBitmap wbitmap = { nullptr };

	// get the icon from the dll
	HICON hicon_small;
	HICON hicon_large;
	if (ExtractIconExA(dll, iconindex, &hicon_large, &hicon_small, 1) > 0) {
		HICON hicon = large ? hicon_large : hicon_small;

		// convert icon to (gdi) bitmap
		ICONINFO info;
		info.hbmColor = nullptr;
		info.hbmMask = nullptr;
		if (GetIconInfo(hicon, &info)) {
			BITMAP bitmap;
			if (GetObjectW(info.hbmColor, sizeof(BITMAP), &bitmap) != 0) {
				size_t bitmap_size = bitmap.bmWidthBytes * bitmap.bmHeight;
				char *bitmap_data = (char*)malloc(bitmap_size);

				// get the pixel data
				if (GetBitmapBits(info.hbmColor, bitmap_size, bitmap_data) != 0) {
					WriteableBitmap wb = WriteableBitmap(bitmap.bmWidth, bitmap.bmHeight);
					void *wb_data = wb.PixelBuffer().data();
					memcpy(wb_data, bitmap_data, bitmap_size);
					wbitmap = wb;
				}
				free(bitmap_data);
			}
			if (info.hbmMask) {
				DeleteObject(info.hbmMask);
			}
			if (info.hbmColor) {
				DeleteObject(info.hbmColor);
			}
		}

		DestroyIcon(hicon_small);
		DestroyIcon(hicon_large);
	}

	return wbitmap;
}

UiIcon* ui_dllicon(const char* dll, int iconindex, bool large) {
	WriteableBitmap wbitmap = ui_dllicon2bitmap(dll, iconindex, large);
	return new UiBitmapIcon(wbitmap);
}

UIEXPORT UiIcon* ui_foldericon(size_t size) {
	bool large = true;
	UiIcon** sys_folder_icon = &sys_folder_icon32;
	if (size <= 24) {
		large = false;
		sys_folder_icon = &sys_folder_icon16;
	}

	if (*sys_folder_icon) {
		return *sys_folder_icon;
	}

	UiIcon* icon = ui_dllicon("shell32.dll", 3, large);
	*sys_folder_icon = icon;
	return icon;
}

UIEXPORT UiIcon* ui_fileicon(size_t size) {
	bool large = true;
	UiIcon** sys_folder_icon = &sys_file_icon32;
	if (size <= 24) {
		large = false;
		sys_folder_icon = &sys_file_icon16;
	}

	if (*sys_folder_icon) {
		return *sys_folder_icon;
	}

	UiIcon* icon = ui_dllicon("shell32.dll", 0, large);
	*sys_folder_icon = icon;
	return icon;
}

mercurial