Skip to content

Commit

Permalink
LunaSvgTest display tooltip on file load error
Browse files Browse the repository at this point in the history
  • Loading branch information
fdwr committed Mar 28, 2022
1 parent 9d3fdec commit 867f270
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 17 deletions.
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ Just a test of [LunaSvg](https://github.com/sammycage/lunasvg) to see how it wor
- Open the CMake project with Visual Studio (confusingly to open a CMake project, you have to open the project via "Open Folder" instead of "Open Project").

## Features
- Opens simple non-animated SVG's. I've seen a few fail to load in LunaSvg if they use other units (like "1em"), but otherwise every one I've tried load.
- Opens simple non-animated SVG's. Nearly every SVG I've tried loads. I've seen a few fail to load in LunaSvg if they use other units (like "1em"), but deleting the "em" from the file or replacing it with the equivalent "px" size fixes it. Some icons don't render quite the same as in the browser environment because of inherited CSS properties, but they do render the same as the browser for the isolated file (e.g. certain Facebook icons).
- Multiple sizes: fixed size, natural size, window size, waterfall display
- Pixel zoom: to see the actual rendering up close
- Grid display
- Pixel zoom: to see the actual rendering up close (Ctrl+mouse wheel or +/- keys)
- Grid display ('g' key)

## Related
## Bug reports
I'm unlikely to add more features to this app, because this is just a side project anyway, but let me know if you encounter bugs in the app itself. Any SVG loading or rendering issues are most likely in LunaSvg (hmm, I should at least display some file load message on error...).

## Related
- LunaSVG - https://github.com/sammycage/lunasvg
- SVG specification - https://github.com/w3c/svgwg/tree/master
1 change: 0 additions & 1 deletion Thoughts.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
Random thoughts for the future:

TODO:
- Diagnose use-test.svg load failure
- Display load failure message
- Make LunaSvg Bitmap.clear faster by writing 32-bits each pixel and create GH PR.
- Move these thoughts below to another file
Expand Down
114 changes: 102 additions & 12 deletions source/LunaSvgTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,24 @@
constexpr size_t MAX_LOADSTRING = 100;
HINSTANCE g_instanceHandle; // Current process base memory address.
HWND g_windowHandle;
HWND g_toolTipWindowHandle;
WCHAR g_applicationTitle[MAX_LOADSTRING]; // The title bar text.
WCHAR g_windowClassName[MAX_LOADSTRING]; // The main window class name.
const HBRUSH g_backgroundWindowBrush = HBRUSH(COLOR_3DFACE+1);

TOOLINFO g_toolTipInfo =
{
.cbSize = sizeof(TOOLINFO),
.uFlags = TTF_IDISHWND | TTF_TRACK | TTF_TRANSPARENT | TTF_ABSOLUTE, //|TTF_CENTERTIP,
.hwnd = nullptr, // containing hwnd
.uId = 0, // tool id/handle
.rect = {0,0,4096,4096},
.hinst = nullptr, // instance handle
.lpszText = const_cast<LPWSTR>(L""), // updated text
.lParam = 0,
.lpReserved = nullptr,
};

enum class BitmapSizingDisplay
{
FixedSize,
Expand Down Expand Up @@ -74,6 +88,17 @@ lunasvg::Bitmap g_bitmap; // Rendered bitmap of all SVG documents.
bool g_svgNeedsRedrawing = true; // Set true after any size changes, layout changes, or background color (not just scrolling or zoom).
bool g_realignBitmap = false; // Set true after loading new files to recenter/realign the new bitmap.
bool g_constrainBitmapOffsets = false; // Set true after resizing to constrain the view over the current bitmap.
std::wstring g_errorMessage;
const std::wstring_view g_defaultMessage =
L"No SVG loaded\r\n"
L"\r\n"
L"Use File/Open or drag&drop filenames to load SVG documents.\r\n"
L"\r\n"
L"mouse wheel = pan vertically\r\n"
L"mouse wheel + shift = pan horizontally\r\n"
L"mouse wheel + ctrl = zoom\r\n"
L"middle mouse drag = pan\r\n"
L"arrow keys/home/end/pgup/pgdn = pan\r\n";

const uint32_t g_waterfallBitmapSizes[] = {16,20,24,28,32,40,48,56,64,72,80,96,112,128,160,192,224,256};
const uint32_t g_zoomFactors[] = {1,2,3,4,6,8,12,16,24,32};
Expand Down Expand Up @@ -241,6 +266,64 @@ ATOM RegisterMainWindowClass(HINSTANCE instanceHandle)
return RegisterClassExW(&wcex);
}


// Create singleton tooltip used for error messages.
void CreateToolTip(HINSTANCE instanceHandle, HWND parentHwnd)
{
g_toolTipInfo.hinst = instanceHandle;
g_toolTipInfo.hwnd = parentHwnd;

g_toolTipWindowHandle = CreateWindowEx(
0,
TOOLTIPS_CLASS,
NULL,
WS_POPUP|TTS_NOANIMATE|TTS_NOFADE|TTS_NOPREFIX,//|TTS_BALLOON|TTS_ALWAYSTIP
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
nullptr,
nullptr,
instanceHandle,
0
);

SetWindowPos(g_toolTipWindowHandle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW);
SendMessage(g_toolTipWindowHandle, TTM_ADDTOOL, 0, (LPARAM)&g_toolTipInfo);
}


void ShowToolTip(
const wchar_t* message,
int32_t toolTipX = 10,
int32_t toolTipY = 10
)
{
// Adjust the client-relative coordinates to screen space.
POINT toolTipPoint = { toolTipX, toolTipY };
ClientToScreen(g_windowHandle, &toolTipPoint);
// auto {toolTipScreenX, toolTipScreenY} = toolTipPoint; // Why C++, why? Be self-consistent, using curly braces.
auto [toolTipScreenX, toolTipScreenY] = toolTipPoint;

//SendMessage(TtHwnd, TTM_SETMAXTIPWIDTH, 0, sz.cx); // No wrapping. Just let it be as wide as it needs to be.
g_toolTipInfo.lpszText = const_cast<LPWSTR>(message);
SendMessage(g_toolTipWindowHandle, TTM_UPDATETIPTEXT, 0, (LPARAM)&g_toolTipInfo);
SendMessage(g_toolTipWindowHandle, TTM_TRACKPOSITION, 0, (LPARAM)(toolTipScreenX | toolTipScreenY << 16)); // reposition one last time
SendMessage(g_toolTipWindowHandle, TTM_TRACKACTIVATE, (WPARAM)true, (LPARAM)&g_toolTipInfo); // now show it so it calcs size
}


void HideToolTip()
{
SendMessage(g_toolTipWindowHandle, TTM_TRACKACTIVATE, (WPARAM)false, (LPARAM)&g_toolTipInfo); // now show it so it calcs size
}


/*TIMERPROC*/void CALLBACK HideToolTipTimerProc(HWND hwnd, UINT uElapse, UINT_PTR uIDEvent, DWORD dwTime)
{
KillTimer(hwnd, uIDEvent);
HideToolTip();
}


// Save the process base memory address in a global variable, and
// create the main program window.
BOOL InitializeWindowInstance(HINSTANCE instanceHandle, int commandShow)
Expand Down Expand Up @@ -273,6 +356,8 @@ BOOL InitializeWindowInstance(HINSTANCE instanceHandle, int commandShow)
ShowWindow(hwnd, commandShow);
UpdateWindow(hwnd);

CreateToolTip(instanceHandle, hwnd);

return TRUE;
}

Expand Down Expand Up @@ -726,6 +811,7 @@ void ClearSvgList()
g_svgDocuments.clear();
g_filenameList.clear();
g_bitmap = lunasvg::Bitmap();
g_errorMessage.clear();
}


Expand All @@ -737,6 +823,12 @@ void AppendSingleSvgFile(wchar_t const* filePath)
g_svgDocuments.push_back(std::move(document));
g_filenameList.push_back(filePath);
}
else
{
wchar_t errorMessage[1000];
_snwprintf_s(errorMessage, sizeof(errorMessage), L"Error loading: %s\n", filePath);
g_errorMessage += errorMessage;
}
RealignBitmapOffsetsLater();
}

Expand All @@ -756,6 +848,13 @@ void LoadSvgFiles(std::vector<std::wstring>&& fileList)
{
AppendSingleSvgFile(fileName.c_str());
}

if (!g_errorMessage.empty())
{
// Show error messages, after two second delay.
ShowToolTip(g_errorMessage.c_str());
SetTimer(g_windowHandle, IDM_OPEN_FILE, 2000, &HideToolTipTimerProc);
}
}


Expand Down Expand Up @@ -1411,22 +1510,13 @@ void RepaintWindow(HWND hwnd)
if (!g_bitmap.valid())
{
FillRect(ps.hdc, &clientRect, g_backgroundWindowBrush);
SetBkMode(ps.hdc, TRANSPARENT);
HFONT oldFont = static_cast<HFONT>(SelectObject(ps.hdc, GetStockObject(DEFAULT_GUI_FONT)));
std::wstring_view message =
L"No SVG loaded\r\n"
L"\r\n"
L"Use File/Open or drag&drop filenames to load SVG documents.\r\n"
L"\r\n"
L"mouse wheel = pan vertically\r\n"
L"mouse wheel + shift = pan horizontally\r\n"
L"mouse wheel + ctrl = zoom\r\n"
L"middle mouse drag = pan\r\n"
L"arrow keys/home/end/pgup/pgdn = pan";
DrawText(ps.hdc, message.data(), int(message.size()), &clientRect, DT_NOCLIP | DT_NOPREFIX | DT_WORDBREAK);
DrawText(ps.hdc, g_defaultMessage.data(), int(g_defaultMessage.size()), &clientRect, DT_NOCLIP | DT_NOPREFIX | DT_WORDBREAK);
SelectObject(ps.hdc, oldFont);
}
// Draw bitmap.
else
else // g_bitmap.valid()
{
BITMAPHEADERv5 bitmapInfo = {};
FillBitmapInfoFromLunaSvgBitmap(g_bitmap, /*out*/ bitmapInfo);
Expand Down
1 change: 1 addition & 0 deletions source/precomp.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
// Windows Header Files
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h> // for tooltip
#include <commdlg.h> // GetOpenFileName
#include <shellapi.h> // DragQueryFile

Expand Down

0 comments on commit 867f270

Please sign in to comment.