mirror of https://github.com/bsnes-emu/bsnes.git
Update to v106r41 release.
byuu says: Changelog: - hiro: added Label::set(Background,Foreground)Color (not implemented on Cocoa backend) - hiro: added (Horizontal,Vertical)Layout::setPadding() - setMargin(m) is now an alias to setPadding({m, m, m, m}) - hiro/Windows: update Label rendering to draw to an offscreen canvas to prevent flickering - sfc: reverted back to 224/240-line height (from 223/239-line height in earlier v106 WIPs) - bsnes: new multi-segment status bar added - bsnes: exiting fullscreen mode will resize and recenter window - this is required; the window geometry gets all scrambled when toggling fullscreen mode - bsnes: updated to a new logo [Ange Albertini] Errata: - hiro/Windows: try to paint Label backgroundColor quicker to avoid startup flicker - `WM_ERASEBKGND` fallthrough to `WM_PAINT` seems to work - hiro/Qt: use Window backgroundColor for Label when no Label backgroundColor set - bsnes: update size multipliers in presentation.cpp to 224/240 (main window size is off in this WIP)
This commit is contained in:
parent
470e27323d
commit
f70a20bc42
|
@ -13,7 +13,7 @@ using namespace nall;
|
|||
|
||||
namespace Emulator {
|
||||
static const string Name = "higan";
|
||||
static const string Version = "106.40";
|
||||
static const string Version = "106.41";
|
||||
static const string Author = "byuu";
|
||||
static const string License = "GPLv3";
|
||||
static const string Website = "https://byuu.org/";
|
||||
|
|
|
@ -120,9 +120,9 @@ auto Interface::title() -> string {
|
|||
auto Interface::videoInformation() -> VideoInformation {
|
||||
VideoInformation vi;
|
||||
vi.width = 256;
|
||||
vi.height = 239;
|
||||
vi.height = 240;
|
||||
vi.internalWidth = 512;
|
||||
vi.internalHeight = 478;
|
||||
vi.internalHeight = 480;
|
||||
vi.aspectCorrection = 8.0 / 7.0;
|
||||
if(Region::NTSC()) vi.refreshRate = system.cpuFrequency() / (262.0 * 1364.0);
|
||||
if(Region::PAL()) vi.refreshRate = system.cpuFrequency() / (312.0 * 1364.0);
|
||||
|
|
|
@ -83,10 +83,10 @@ auto PPU::scanline() -> void {
|
|||
|
||||
auto PPU::refresh() -> void {
|
||||
auto output = this->output;
|
||||
if(!overscan()) output -= 12 * 512;
|
||||
if(!overscan()) output -= 14 * 512;
|
||||
auto pitch = 512 << !interlace();
|
||||
auto width = 256 << hires();
|
||||
auto height = 239 << interlace();
|
||||
auto height = 240 << interlace();
|
||||
Emulator::video.setEffect(Emulator::Video::Effect::ColorBleed, settings.blurEmulation && hires());
|
||||
Emulator::video.refresh(output, pitch * sizeof(uint32), width, height);
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ auto PPU::load(Markup::Node node) -> bool {
|
|||
auto PPU::power(bool reset) -> void {
|
||||
create(Enter, system.cpuFrequency());
|
||||
PPUcounter::reset();
|
||||
memory::fill<uint32>(output, 512 * 478);
|
||||
memory::fill<uint32>(output, 512 * 480);
|
||||
|
||||
function<auto (uint24, uint8) -> uint8> reader{&PPU::readIO, this};
|
||||
function<auto (uint24, uint8) -> void> writer{&PPU::writeIO, this};
|
||||
|
|
|
@ -239,10 +239,10 @@ auto PPU::refresh() -> void {
|
|||
}
|
||||
|
||||
auto output = this->output;
|
||||
if(!overscan()) output -= 12 * 512;
|
||||
if(!overscan()) output -= 14 * 512;
|
||||
auto pitch = 512;
|
||||
auto width = 512;
|
||||
auto height = 478;
|
||||
auto height = 480;
|
||||
Emulator::video.setEffect(Emulator::Video::Effect::ColorBleed, settings.blurEmulation);
|
||||
Emulator::video.refresh(output, pitch * sizeof(uint32), width, height);
|
||||
}
|
||||
|
|
|
@ -99,7 +99,11 @@ Presentation::Presentation() {
|
|||
});
|
||||
showStatusBar.setText("Show Status Bar").setChecked(settings["UserInterface/ShowStatusBar"].boolean()).onToggle([&] {
|
||||
settings["UserInterface/ShowStatusBar"].setValue(showStatusBar.checked());
|
||||
statusBar.setVisible(showStatusBar.checked());
|
||||
if(!showStatusBar.checked()) {
|
||||
layout.remove(statusLayout);
|
||||
} else {
|
||||
layout.append(statusLayout, Size{~0, StatusHeight});
|
||||
}
|
||||
if(visible()) resizeWindow();
|
||||
});
|
||||
videoSettings.setText("Video ...").onActivate([&] { settingsWindow->show(0); });
|
||||
|
@ -143,9 +147,21 @@ Presentation::Presentation() {
|
|||
setFocused();
|
||||
});
|
||||
|
||||
statusBar.setFont(Font().setBold());
|
||||
statusBar.setVisible(settings["UserInterface/ShowStatusBar"].boolean());
|
||||
program->updateMessage();
|
||||
if(!settings["UserInterface/ShowStatusBar"].boolean()) {
|
||||
layout.remove(statusLayout);
|
||||
}
|
||||
|
||||
statusLeft.setFont(Font().setBold());
|
||||
statusLeft.setAlignment(0.0);
|
||||
statusLeft.setBackgroundColor({ 32, 32, 32});
|
||||
statusLeft.setForegroundColor({255, 255, 255});
|
||||
|
||||
statusRight.setFont(Font().setBold());
|
||||
statusRight.setAlignment(1.0);
|
||||
statusRight.setBackgroundColor({ 32, 32, 32});
|
||||
statusRight.setForegroundColor({255, 255, 255});
|
||||
|
||||
program->updateStatus();
|
||||
|
||||
onClose([&] {
|
||||
program->quit();
|
||||
|
@ -200,7 +216,7 @@ auto Presentation::clearViewport() -> void {
|
|||
if(!video) return;
|
||||
|
||||
if(!emulator->loaded()) {
|
||||
viewport.setGeometry({0, 0, geometry().width(), geometry().height()});
|
||||
viewportLayout.setPadding();
|
||||
}
|
||||
|
||||
uint32_t* output;
|
||||
|
@ -219,75 +235,76 @@ auto Presentation::clearViewport() -> void {
|
|||
}
|
||||
|
||||
auto Presentation::resizeViewport() -> void {
|
||||
uint windowWidth = geometry().width();
|
||||
uint windowHeight = geometry().height();
|
||||
if(!emulator->loaded()) return clearViewport();
|
||||
|
||||
if(!emulator->loaded()) {
|
||||
viewport.setGeometry({0, 0, windowWidth, windowHeight});
|
||||
return clearViewport();
|
||||
}
|
||||
uint windowWidth = viewportLayout.geometry().width();
|
||||
uint windowHeight = viewportLayout.geometry().height();
|
||||
|
||||
uint width = 256 * (settings["View/AspectCorrection"].boolean() ? 8.0 / 7.0 : 1.0);
|
||||
uint height = (settings["View/OverscanCropping"].boolean() ? 223.0 : 239.0);
|
||||
uint viewportWidth, viewportHeight;
|
||||
|
||||
if(settings["View/IntegralScaling"].boolean()) {
|
||||
uint widthMultiplier = windowWidth / width;
|
||||
uint heightMultiplier = windowHeight / height;
|
||||
uint multiplier = min(widthMultiplier, heightMultiplier);
|
||||
uint viewportWidth = width * multiplier;
|
||||
uint viewportHeight = height * multiplier;
|
||||
viewport.setGeometry({
|
||||
(windowWidth - viewportWidth) / 2, (windowHeight - viewportHeight) / 2,
|
||||
viewportWidth, viewportHeight
|
||||
});
|
||||
viewportWidth = width * multiplier;
|
||||
viewportHeight = height * multiplier;
|
||||
} else {
|
||||
double widthMultiplier = (double)windowWidth / width;
|
||||
double heightMultiplier = (double)windowHeight / height;
|
||||
double multiplier = min(widthMultiplier, heightMultiplier);
|
||||
uint viewportWidth = width * multiplier;
|
||||
uint viewportHeight = height * multiplier;
|
||||
viewport.setGeometry({
|
||||
(windowWidth - viewportWidth) / 2, (windowHeight - viewportHeight) / 2,
|
||||
viewportWidth, viewportHeight
|
||||
});
|
||||
viewportWidth = width * multiplier;
|
||||
viewportHeight = height * multiplier;
|
||||
}
|
||||
|
||||
uint paddingWidth = (windowWidth - viewportWidth) / 2;
|
||||
uint paddingHeight = (windowHeight - viewportHeight) / 2;
|
||||
viewportLayout.setPadding({
|
||||
paddingWidth / 2, paddingHeight / 2,
|
||||
paddingWidth - paddingWidth / 2, paddingHeight - paddingHeight / 2
|
||||
});
|
||||
|
||||
clearViewport();
|
||||
}
|
||||
|
||||
auto Presentation::resizeWindow() -> void {
|
||||
uint width = 256 * (settings["View/AspectCorrection"].boolean() ? 8.0 / 7.0 : 1.0);
|
||||
uint height = (settings["View/OverscanCropping"].boolean() ? 223.0 : 239.0);
|
||||
uint statusHeight = settings["UserInterface/ShowStatusBar"].boolean() ? StatusHeight : 0;
|
||||
|
||||
uint multiplier = 2;
|
||||
if(settings["View/Size"].text() == "Small" ) multiplier = 2;
|
||||
if(settings["View/Size"].text() == "Medium") multiplier = 3;
|
||||
if(settings["View/Size"].text() == "Large" ) multiplier = 4;
|
||||
|
||||
setSize({width * multiplier, height * multiplier});
|
||||
setSize({width * multiplier, height * multiplier + statusHeight});
|
||||
resizeViewport();
|
||||
}
|
||||
|
||||
auto Presentation::toggleFullscreenMode() -> void {
|
||||
if(!fullScreen()) {
|
||||
statusBar.setVisible(false);
|
||||
if(settings["UserInterface/ShowStatusBar"].boolean()) {
|
||||
layout.remove(statusLayout);
|
||||
}
|
||||
menuBar.setVisible(false);
|
||||
setFullScreen(true);
|
||||
video->setExclusive(settings["Video/Exclusive"].boolean());
|
||||
if(video->exclusive()) setVisible(false);
|
||||
if(!input->acquired()) input->acquire();
|
||||
resizeViewport();
|
||||
} else {
|
||||
if(input->acquired()) input->release();
|
||||
if(video->exclusive()) setVisible(true);
|
||||
video->setExclusive(false);
|
||||
setFullScreen(false);
|
||||
menuBar.setVisible(true);
|
||||
statusBar.setVisible(settings["UserInterface/ShowStatusBar"].boolean());
|
||||
if(settings["UserInterface/ShowStatusBar"].boolean()) {
|
||||
layout.append(statusLayout, Size{~0, StatusHeight});
|
||||
}
|
||||
resizeWindow();
|
||||
setCentered();
|
||||
}
|
||||
//hack: give window geometry time to update after toggling fullscreen and menu/status bars
|
||||
usleep(20 * 1000);
|
||||
Application::processEvents();
|
||||
resizeViewport();
|
||||
}
|
||||
|
||||
auto Presentation::updateRecentGames() -> void {
|
||||
|
|
|
@ -2,7 +2,7 @@ struct AboutWindow : Window {
|
|||
AboutWindow();
|
||||
|
||||
VerticalLayout layout{this};
|
||||
Canvas canvas{&layout, Size{400, 86}, 0};
|
||||
Canvas canvas{&layout, Size{400, 85}, 0};
|
||||
HorizontalLayout informationLayout{&layout, Size{~0, ~0}};
|
||||
Label informationLeft{&informationLayout, Size{~0, 0}, 3};
|
||||
Label informationRight{&informationLayout, Size{~0, 0}};
|
||||
|
@ -10,12 +10,14 @@ struct AboutWindow : Window {
|
|||
|
||||
struct Presentation : Window {
|
||||
enum : uint { RecentGames = 9, QuickStates = 9 };
|
||||
enum : uint { StatusHeight = 25 };
|
||||
|
||||
Presentation();
|
||||
auto drawIcon(uint32_t* output, uint length, uint width, uint height) -> void;
|
||||
auto clearViewport() -> void;
|
||||
auto resizeViewport() -> void;
|
||||
auto resizeWindow() -> void;
|
||||
auto updateStatus() -> void;
|
||||
auto toggleFullscreenMode() -> void;
|
||||
auto clearRecentGames() -> void;
|
||||
auto updateRecentGames() -> void;
|
||||
|
@ -65,10 +67,12 @@ struct Presentation : Window {
|
|||
Menu helpMenu{&menuBar};
|
||||
MenuItem about{&helpMenu};
|
||||
|
||||
FixedLayout layout{this};
|
||||
Viewport viewport{&layout, Geometry{0, 0, 1, 1}};
|
||||
|
||||
StatusBar statusBar{this};
|
||||
VerticalLayout layout{this};
|
||||
HorizontalLayout viewportLayout{&layout, Size{~0, ~0}, 0};
|
||||
Viewport viewport{&viewportLayout, Size{~0, ~0}, 0};
|
||||
HorizontalLayout statusLayout{&layout, Size{~0, StatusHeight}, 0};
|
||||
Label statusLeft{&statusLayout, Size{~0, ~0}, 0};
|
||||
Label statusRight{&statusLayout, Size{80, ~0}, 0};
|
||||
};
|
||||
|
||||
extern unique_pointer<AboutWindow> aboutWindow;
|
||||
|
|
|
@ -93,8 +93,8 @@ auto Program::videoRefresh(const uint32* data, uint pitch, uint width, uint heig
|
|||
|
||||
pitch >>= 2;
|
||||
if(presentation->overscanCropping.checked()) {
|
||||
if(height == 239) data += 8 * pitch, height -= 16;
|
||||
if(height == 478) data += 16 * pitch, height -= 32;
|
||||
if(height == 240) data += 8 * pitch, height -= 16;
|
||||
if(height == 480) data += 16 * pitch, height -= 32;
|
||||
}
|
||||
|
||||
if(video->lock(output, length, width, height)) {
|
||||
|
@ -115,7 +115,7 @@ auto Program::videoRefresh(const uint32* data, uint pitch, uint width, uint heig
|
|||
current = chrono::timestamp();
|
||||
if(current != previous) {
|
||||
previous = current;
|
||||
statusText = {emulator->get("Mode").get<string>(), "FPS: ", frameCounter};
|
||||
showFrameRate({frameCounter, " FPS"});
|
||||
frameCounter = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ Program::Program(string_vector arguments) {
|
|||
}
|
||||
|
||||
auto Program::main() -> void {
|
||||
updateMessage();
|
||||
updateStatus();
|
||||
video->poll();
|
||||
inputManager->poll();
|
||||
inputManager->pollHotkeys();
|
||||
|
|
|
@ -47,7 +47,8 @@ struct Program : Emulator::Platform {
|
|||
auto connectDevices() -> void;
|
||||
auto applyHacks() -> void;
|
||||
auto showMessage(string text) -> void;
|
||||
auto updateMessage() -> void;
|
||||
auto showFrameRate(string text) -> void;
|
||||
auto updateStatus() -> void;
|
||||
auto focused() -> bool;
|
||||
|
||||
public:
|
||||
|
@ -79,9 +80,9 @@ public:
|
|||
|
||||
uint64 autoSaveTime;
|
||||
|
||||
string statusText;
|
||||
string statusMessage;
|
||||
uint64 statusTime;
|
||||
string statusMessage;
|
||||
string statusFrameRate;
|
||||
};
|
||||
|
||||
extern unique_pointer<Program> program;
|
||||
|
|
|
@ -72,6 +72,7 @@ auto Program::applyHacks() -> void {
|
|||
auto label = superNintendo.label;
|
||||
if(label == "AIR STRIKE PATROL" || label == "DESERT FIGHTER") fastPPU = false;
|
||||
if(label == "KOUSHIEN_2") fastDSP = false;
|
||||
if(label == "RENDERING RANGER R2") fastDSP = false;
|
||||
|
||||
emulator->set("Fast PPU", fastPPU);
|
||||
emulator->set("Fast DSP", fastDSP);
|
||||
|
@ -82,30 +83,39 @@ auto Program::showMessage(string text) -> void {
|
|||
statusMessage = text;
|
||||
}
|
||||
|
||||
auto Program::updateMessage() -> void {
|
||||
uint64 currentTime = chrono::timestamp();
|
||||
auto Program::showFrameRate(string text) -> void {
|
||||
statusFrameRate = text;
|
||||
}
|
||||
|
||||
string text;
|
||||
if((currentTime - statusTime) <= 2) {
|
||||
text = statusMessage;
|
||||
} else if(!emulator->loaded()) {
|
||||
text = "No game loaded";
|
||||
} else if(presentation->pauseEmulation.checked()) {
|
||||
text = "Paused";
|
||||
} else if(!focused() && settingsWindow->input.pauseEmulation.checked()) {
|
||||
text = "Paused";
|
||||
} else {
|
||||
text = statusText;
|
||||
auto Program::updateStatus() -> void {
|
||||
string message;
|
||||
if(chrono::timestamp() - statusTime <= 2) {
|
||||
message = statusMessage;
|
||||
}
|
||||
message.prepend(" ");
|
||||
if(message != presentation->statusLeft.text()) {
|
||||
presentation->statusLeft.setText(message);
|
||||
}
|
||||
|
||||
if(text != presentation->statusBar.text()) {
|
||||
presentation->statusBar.setText(text);
|
||||
string frameRate;
|
||||
if(!emulator->loaded()) {
|
||||
frameRate = "Unloaded";
|
||||
} else if(presentation->pauseEmulation.checked()) {
|
||||
frameRate = "Paused";
|
||||
} else if(!focused() && settingsWindow->input.pauseEmulation.checked()) {
|
||||
frameRate = "Paused";
|
||||
} else {
|
||||
frameRate = statusFrameRate;
|
||||
}
|
||||
frameRate.append(" ");
|
||||
if(frameRate != presentation->statusRight.text()) {
|
||||
presentation->statusRight.setText(frameRate);
|
||||
}
|
||||
}
|
||||
|
||||
auto Program::focused() -> bool {
|
||||
//exclusive mode creates its own top-level window: presentation window will not have focus
|
||||
if(video->exclusive()) return true;
|
||||
if(video && video->exclusive()) return true;
|
||||
if(presentation && presentation->focused()) return true;
|
||||
return false;
|
||||
}
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
File diff suppressed because it is too large
Load Diff
|
@ -48,6 +48,14 @@ auto pLabel::setAlignment(Alignment alignment) -> void {
|
|||
}
|
||||
}
|
||||
|
||||
auto pLabel::setBackgroundColor(Color color) -> void {
|
||||
//todo
|
||||
}
|
||||
|
||||
auto pLabel::setForegroundColor(Color color) -> void {
|
||||
//todo
|
||||
}
|
||||
|
||||
auto pLabel::setGeometry(Geometry geometry) -> void {
|
||||
//NSTextView does not support vertical text centering:
|
||||
//simulate this by adjusting the geometry placement (reduce height, move view down)
|
||||
|
|
|
@ -14,6 +14,8 @@ struct pLabel : pWidget {
|
|||
|
||||
auto minimumSize() const -> Size override;
|
||||
auto setAlignment(Alignment alignment) -> void;
|
||||
auto setBackgroundColor(Color color) -> void;
|
||||
auto setForegroundColor(Color color) -> void;
|
||||
auto setGeometry(Geometry geometry) -> void override;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
|
|
|
@ -1395,13 +1395,19 @@ struct mLabel : mWidget {
|
|||
Declare(Label)
|
||||
|
||||
auto alignment() const -> Alignment;
|
||||
auto backgroundColor() const -> Color;
|
||||
auto foregroundColor() const -> Color;
|
||||
auto setAlignment(Alignment alignment = {}) -> type&;
|
||||
auto setBackgroundColor(Color color = {}) -> type&;
|
||||
auto setForegroundColor(Color color = {}) -> type&;
|
||||
auto setText(const string& text = "") -> type&;
|
||||
auto text() const -> string;
|
||||
|
||||
//private:
|
||||
struct State {
|
||||
Alignment alignment;
|
||||
Color backgroundColor;
|
||||
Color foregroundColor;
|
||||
string text;
|
||||
} state;
|
||||
};
|
||||
|
|
|
@ -497,7 +497,11 @@ struct Label : sLabel {
|
|||
using internalType = mLabel;
|
||||
|
||||
auto alignment() const { return self().alignment(); }
|
||||
auto backgroundColor() const { return self().backgroundColor(); }
|
||||
auto foregroundColor() const { return self().foregroundColor(); }
|
||||
auto setAlignment(Alignment alignment = {}) { return self().setAlignment(alignment), *this; }
|
||||
auto setBackgroundColor(Color color = {}) { return self().setBackgroundColor(color), *this; }
|
||||
auto setForegroundColor(Color color = {}) { return self().setForegroundColor(color), *this; }
|
||||
auto setText(const string& text = "") { return self().setText(text), *this; }
|
||||
auto text() const { return self().text(); }
|
||||
};
|
||||
|
|
|
@ -10,12 +10,32 @@ auto mLabel::alignment() const -> Alignment {
|
|||
return state.alignment;
|
||||
}
|
||||
|
||||
auto mLabel::backgroundColor() const -> Color {
|
||||
return state.backgroundColor;
|
||||
}
|
||||
|
||||
auto mLabel::foregroundColor() const -> Color {
|
||||
return state.foregroundColor;
|
||||
}
|
||||
|
||||
auto mLabel::setAlignment(Alignment alignment) -> type& {
|
||||
state.alignment = alignment;
|
||||
signal(setAlignment, alignment);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto mLabel::setBackgroundColor(Color color) -> type& {
|
||||
state.backgroundColor = color;
|
||||
signal(setBackgroundColor, color);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto mLabel::setForegroundColor(Color color) -> type& {
|
||||
state.foregroundColor = color;
|
||||
signal(setForegroundColor, color);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto mLabel::setText(const string& text) -> type& {
|
||||
state.text = text;
|
||||
signal(setText, text);
|
||||
|
|
|
@ -38,7 +38,10 @@ auto mHorizontalLayout::minimumSize() const -> Size {
|
|||
height = max(height, child.height());
|
||||
}
|
||||
|
||||
return {settings.margin * 2 + width, settings.margin * 2 + height};
|
||||
return {
|
||||
settings.padding.x() + width + settings.padding.width(),
|
||||
settings.padding.y() + height + settings.padding.height()
|
||||
};
|
||||
}
|
||||
|
||||
auto mHorizontalLayout::remove(sSizable sizable) -> type& {
|
||||
|
@ -85,10 +88,10 @@ auto mHorizontalLayout::setGeometry(Geometry containerGeometry) -> type& {
|
|||
}
|
||||
|
||||
Geometry geometry = containerGeometry;
|
||||
geometry.setX (geometry.x() + settings.margin );
|
||||
geometry.setY (geometry.y() + settings.margin );
|
||||
geometry.setWidth (geometry.width() - settings.margin * 2);
|
||||
geometry.setHeight(geometry.height() - settings.margin * 2);
|
||||
geometry.setX (geometry.x() + settings.padding.x());
|
||||
geometry.setY (geometry.y() + settings.padding.y());
|
||||
geometry.setWidth (geometry.width() - settings.padding.x() - settings.padding.width());
|
||||
geometry.setHeight(geometry.height() - settings.padding.y() - settings.padding.height());
|
||||
|
||||
float minimumWidth = 0, maximumWidthCounter = 0;
|
||||
for(auto& child : properties) {
|
||||
|
@ -121,12 +124,19 @@ auto mHorizontalLayout::setGeometry(Geometry containerGeometry) -> type& {
|
|||
}
|
||||
|
||||
auto mHorizontalLayout::setMargin(float margin) -> type& {
|
||||
settings.margin = margin;
|
||||
setPadding({margin, margin, margin, margin});
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto mHorizontalLayout::setPadding(Geometry padding) -> type& {
|
||||
settings.padding = padding;
|
||||
setGeometry(geometry());
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto mHorizontalLayout::setSpacing(float spacing) -> type& {
|
||||
settings.spacing = spacing;
|
||||
setGeometry(geometry());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,12 +15,13 @@ struct mHorizontalLayout : mLayout {
|
|||
auto setFont(const Font& font = {}) -> type& override;
|
||||
auto setGeometry(Geometry geometry) -> type& override;
|
||||
auto setMargin(float margin = 0) -> type&;
|
||||
auto setPadding(Geometry padding = {}) -> type&;
|
||||
auto setSpacing(float spacing = 5) -> type&;
|
||||
auto setVisible(bool visible = true) -> type&;
|
||||
|
||||
struct Settings {
|
||||
float alignment = 0.5;
|
||||
float margin = 0;
|
||||
Geometry padding;
|
||||
float spacing = 5;
|
||||
} settings;
|
||||
|
||||
|
|
|
@ -13,11 +13,12 @@ using sHorizontalLayout = shared_pointer<mHorizontalLayout>;
|
|||
struct HorizontalLayout : sHorizontalLayout {
|
||||
DeclareSharedLayout(HorizontalLayout)
|
||||
|
||||
auto append(sSizable sizable, Size size, signed spacing = 5) { return self().append(sizable, size, spacing), *this; }
|
||||
auto modify(sSizable sizable, Size size, signed spacing = 5) { return self().modify(sizable, size, spacing), *this; }
|
||||
auto setAlignment(double alignment = 0.5) { return self().setAlignment(alignment), *this; }
|
||||
auto setMargin(signed margin = 0) { return self().setMargin(margin), *this; }
|
||||
auto setSpacing(signed spacing = 5) { return self().setSpacing(spacing), *this; }
|
||||
auto append(sSizable sizable, Size size, float spacing = 5) { return self().append(sizable, size, spacing), *this; }
|
||||
auto modify(sSizable sizable, Size size, float spacing = 5) { return self().modify(sizable, size, spacing), *this; }
|
||||
auto setAlignment(float alignment = 0.5) { return self().setAlignment(alignment), *this; }
|
||||
auto setMargin(float margin = 0) { return self().setMargin(margin), *this; }
|
||||
auto setPadding(Geometry padding = {}) { return self().setPadding(padding), *this; }
|
||||
auto setSpacing(float spacing = 5) { return self().setSpacing(spacing), *this; }
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -26,11 +27,12 @@ using sVerticalLayout = shared_pointer<mVerticalLayout>;
|
|||
struct VerticalLayout : sVerticalLayout {
|
||||
DeclareSharedLayout(VerticalLayout)
|
||||
|
||||
auto append(sSizable sizable, Size size, signed spacing = 5) { return self().append(sizable, size, spacing), *this; }
|
||||
auto modify(sSizable sizable, Size size, signed spacing = 5) { return self().modify(sizable, size, spacing), *this; }
|
||||
auto setAlignment(double alignment = 0.0) { return self().setAlignment(alignment), *this; }
|
||||
auto setMargin(signed margin = 0) { return self().setMargin(margin), *this; }
|
||||
auto setSpacing(signed spacing = 5) { return self().setSpacing(spacing), *this; }
|
||||
auto append(sSizable sizable, Size size, float spacing = 5) { return self().append(sizable, size, spacing), *this; }
|
||||
auto modify(sSizable sizable, Size size, float spacing = 5) { return self().modify(sizable, size, spacing), *this; }
|
||||
auto setAlignment(float alignment = 0.0) { return self().setAlignment(alignment), *this; }
|
||||
auto setMargin(float margin = 0) { return self().setMargin(margin), *this; }
|
||||
auto setPadding(Geometry padding = {}) { return self().setPadding(padding), *this; }
|
||||
auto setSpacing(float spacing = 5) { return self().setSpacing(spacing), *this; }
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -38,7 +38,10 @@ auto mVerticalLayout::minimumSize() const -> Size {
|
|||
if(&child != &properties.right()) height += child.spacing();
|
||||
}
|
||||
|
||||
return {settings.margin * 2 + width, settings.margin * 2 + height};
|
||||
return {
|
||||
settings.padding.x() + width + settings.padding.width(),
|
||||
settings.padding.y() + height + settings.padding.height()
|
||||
};
|
||||
}
|
||||
|
||||
auto mVerticalLayout::remove(sSizable sizable) -> type& {
|
||||
|
@ -85,10 +88,10 @@ auto mVerticalLayout::setGeometry(Geometry containerGeometry) -> type& {
|
|||
}
|
||||
|
||||
Geometry geometry = containerGeometry;
|
||||
geometry.setX (geometry.x() + settings.margin );
|
||||
geometry.setY (geometry.y() + settings.margin );
|
||||
geometry.setWidth (geometry.width() - settings.margin * 2);
|
||||
geometry.setHeight(geometry.height() - settings.margin * 2);
|
||||
geometry.setX (geometry.x() + settings.padding.x());
|
||||
geometry.setY (geometry.y() + settings.padding.y());
|
||||
geometry.setWidth (geometry.width() - settings.padding.x() - settings.padding.width());
|
||||
geometry.setHeight(geometry.height() - settings.padding.y() - settings.padding.height());
|
||||
|
||||
float minimumHeight = 0, maximumHeightCounter = 0;
|
||||
for(auto& child : properties) {
|
||||
|
@ -121,12 +124,19 @@ auto mVerticalLayout::setGeometry(Geometry containerGeometry) -> type& {
|
|||
}
|
||||
|
||||
auto mVerticalLayout::setMargin(float margin) -> type& {
|
||||
settings.margin = margin;
|
||||
setPadding({margin, margin, margin, margin});
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto mVerticalLayout::setPadding(Geometry padding) -> type& {
|
||||
settings.padding = padding;
|
||||
setGeometry(geometry());
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto mVerticalLayout::setSpacing(float spacing) -> type& {
|
||||
settings.spacing = spacing;
|
||||
setGeometry(geometry());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,12 +15,13 @@ struct mVerticalLayout : mLayout {
|
|||
auto setFont(const Font& font = {}) -> type& override;
|
||||
auto setGeometry(Geometry geometry) -> type& override;
|
||||
auto setMargin(float margin = 0) -> type&;
|
||||
auto setPadding(Geometry padding = {}) -> type&;
|
||||
auto setSpacing(float spacing = 5) -> type&;
|
||||
auto setVisible(bool visible = true) -> type& override;
|
||||
|
||||
struct Settings {
|
||||
float alignment = 0.0;
|
||||
float margin = 0;
|
||||
Geometry padding;
|
||||
float spacing = 5;
|
||||
} settings;
|
||||
|
||||
|
|
|
@ -3,15 +3,21 @@
|
|||
namespace hiro {
|
||||
|
||||
auto pLabel::construct() -> void {
|
||||
gtkWidget = gtk_label_new("");
|
||||
gtkWidget = gtk_event_box_new();
|
||||
subWidget = gtk_label_new("");
|
||||
gtk_widget_show(subWidget);
|
||||
gtk_container_add(GTK_CONTAINER(gtkWidget), subWidget);
|
||||
|
||||
setAlignment(state().alignment);
|
||||
setBackgroundColor(state().backgroundColor);
|
||||
setForegroundColor(state().foregroundColor);
|
||||
setText(state().text);
|
||||
|
||||
pWidget::construct();
|
||||
}
|
||||
|
||||
auto pLabel::destruct() -> void {
|
||||
gtk_widget_destroy(subWidget);
|
||||
gtk_widget_destroy(gtkWidget);
|
||||
}
|
||||
|
||||
|
@ -22,15 +28,31 @@ auto pLabel::minimumSize() const -> Size {
|
|||
|
||||
auto pLabel::setAlignment(Alignment alignment) -> void {
|
||||
if(!alignment) alignment = {0.0, 0.5};
|
||||
gtk_misc_set_alignment(GTK_MISC(gtkWidget), alignment.horizontal(), alignment.vertical());
|
||||
gtk_misc_set_alignment(GTK_MISC(subWidget), alignment.horizontal(), alignment.vertical());
|
||||
auto justify = GTK_JUSTIFY_CENTER;
|
||||
if(alignment.horizontal() < 0.333) justify = GTK_JUSTIFY_LEFT;
|
||||
if(alignment.horizontal() > 0.666) justify = GTK_JUSTIFY_RIGHT;
|
||||
gtk_label_set_justify(GTK_LABEL(gtkWidget), justify);
|
||||
gtk_label_set_justify(GTK_LABEL(subWidget), justify);
|
||||
}
|
||||
|
||||
auto pLabel::setBackgroundColor(Color color) -> void {
|
||||
if(!color) color = self().parentWindow(true)->backgroundColor();
|
||||
auto gdkColor = CreateColor(color);
|
||||
gtk_widget_modify_bg(gtkWidget, GTK_STATE_NORMAL, color ? &gdkColor : nullptr);
|
||||
}
|
||||
|
||||
auto pLabel::setForegroundColor(Color color) -> void {
|
||||
auto gdkColor = CreateColor(color);
|
||||
gtk_widget_modify_fg(subWidget, GTK_STATE_NORMAL, color ? &gdkColor : nullptr);
|
||||
}
|
||||
|
||||
auto pLabel::setText(const string& text) -> void {
|
||||
gtk_label_set_text(GTK_LABEL(gtkWidget), text);
|
||||
gtk_label_set_text(GTK_LABEL(subWidget), text);
|
||||
}
|
||||
|
||||
auto pLabel::setVisible(bool visible) -> void {
|
||||
setBackgroundColor(state().backgroundColor);
|
||||
return pWidget::setVisible(visible);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,7 +7,12 @@ struct pLabel : pWidget {
|
|||
|
||||
auto minimumSize() const -> Size override;
|
||||
auto setAlignment(Alignment alignment) -> void;
|
||||
auto setBackgroundColor(Color color) -> void;
|
||||
auto setForegroundColor(Color color) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
auto setVisible(bool visible) -> void override;
|
||||
|
||||
GtkWidget* subWidget = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
1194
hiro/qt/qt.moc
1194
hiro/qt/qt.moc
File diff suppressed because it is too large
Load Diff
|
@ -5,10 +5,11 @@ namespace hiro {
|
|||
auto pLabel::construct() -> void {
|
||||
qtWidget = qtLabel = new QLabel;
|
||||
|
||||
setAlignment(state().alignment);
|
||||
setText(state().text);
|
||||
|
||||
pWidget::construct();
|
||||
setAlignment(state().alignment);
|
||||
setBackgroundColor(state().backgroundColor);
|
||||
setForegroundColor(state().foregroundColor);
|
||||
setText(state().text);
|
||||
}
|
||||
|
||||
auto pLabel::destruct() -> void {
|
||||
|
@ -26,6 +27,29 @@ auto pLabel::setAlignment(Alignment alignment) -> void {
|
|||
qtLabel->setAlignment((Qt::Alignment)CalculateAlignment(alignment));
|
||||
}
|
||||
|
||||
auto pLabel::setBackgroundColor(Color color) -> void {
|
||||
if(color) {
|
||||
QPalette palette = qtLabel->palette();
|
||||
palette.setColor(QPalette::Base, QColor(color.red(), color.green(), color.blue()));
|
||||
qtLabel->setBackgroundRole(QPalette::Base);
|
||||
qtLabel->setPalette(palette);
|
||||
qtLabel->setAutoFillBackground(true);
|
||||
} else {
|
||||
//todo
|
||||
}
|
||||
}
|
||||
|
||||
auto pLabel::setForegroundColor(Color color) -> void {
|
||||
if(color) {
|
||||
QPalette palette = qtLabel->palette();
|
||||
palette.setColor(QPalette::Text, QColor(color.red(), color.green(), color.blue()));
|
||||
qtLabel->setForegroundRole(QPalette::Text);
|
||||
qtLabel->setPalette(palette);
|
||||
} else {
|
||||
//todo
|
||||
}
|
||||
}
|
||||
|
||||
auto pLabel::setText(const string& text) -> void {
|
||||
qtLabel->setText(QString::fromUtf8(text));
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ struct pLabel : pWidget {
|
|||
|
||||
auto minimumSize() const -> Size override;
|
||||
auto setAlignment(Alignment alignment) -> void;
|
||||
auto setBackgroundColor(Color color) -> void;
|
||||
auto setForegroundColor(Color color) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
QLabel* qtLabel = nullptr;
|
||||
|
|
|
@ -8,7 +8,6 @@ auto pLabel::construct() -> void {
|
|||
0, 0, 0, 0, _parentHandle(), nullptr, GetModuleHandle(0), 0);
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&reference);
|
||||
pWidget::_setState();
|
||||
setAlignment(state().alignment);
|
||||
setText(state().text);
|
||||
}
|
||||
|
||||
|
@ -25,6 +24,14 @@ auto pLabel::setAlignment(Alignment alignment) -> void {
|
|||
InvalidateRect(hwnd, 0, false);
|
||||
}
|
||||
|
||||
auto pLabel::setBackgroundColor(Color color) -> void {
|
||||
InvalidateRect(hwnd, 0, false);
|
||||
}
|
||||
|
||||
auto pLabel::setForegroundColor(Color color) -> void {
|
||||
InvalidateRect(hwnd, 0, false);
|
||||
}
|
||||
|
||||
auto pLabel::setText(const string& text) -> void {
|
||||
SetWindowText(hwnd, utf16_t(text));
|
||||
InvalidateRect(hwnd, 0, false);
|
||||
|
@ -44,20 +51,32 @@ static auto CALLBACK Label_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
|
|||
BeginPaint(hwnd, &ps);
|
||||
RECT rc;
|
||||
GetClientRect(hwnd, &rc);
|
||||
//todo: use DrawThemeParentBackground if Label is inside TabFrame
|
||||
if(auto brush = window->self()->hbrush) {
|
||||
FillRect(ps.hdc, &rc, brush);
|
||||
} else {
|
||||
DrawThemeParentBackground(hwnd, ps.hdc, &rc);
|
||||
}
|
||||
SetBkMode(ps.hdc, TRANSPARENT);
|
||||
SelectObject(ps.hdc, label->self()->hfont);
|
||||
|
||||
auto hdcMemory = CreateCompatibleDC(ps.hdc);
|
||||
auto hbmMemory = CreateCompatibleBitmap(ps.hdc, rc.right - rc.left, rc.bottom - rc.top);
|
||||
SelectObject(hdcMemory, hbmMemory);
|
||||
|
||||
uint length = GetWindowTextLength(hwnd);
|
||||
wchar_t text[length + 1];
|
||||
GetWindowText(hwnd, text, length + 1);
|
||||
text[length] = 0;
|
||||
DrawText(ps.hdc, text, -1, &rc, DT_CALCRECT | DT_END_ELLIPSIS);
|
||||
|
||||
//todo: use DrawThemeParentBackground if Label is inside TabFrame
|
||||
if(auto color = label->backgroundColor()) {
|
||||
auto brush = CreateSolidBrush(CreateRGB(color));
|
||||
FillRect(hdcMemory, &rc, brush);
|
||||
DeleteObject(brush);
|
||||
} else if(auto brush = window->self()->hbrush) {
|
||||
FillRect(hdcMemory, &rc, brush);
|
||||
} else {
|
||||
DrawThemeParentBackground(hwnd, hdcMemory, &rc);
|
||||
}
|
||||
|
||||
SetBkMode(hdcMemory, TRANSPARENT);
|
||||
SelectObject(hdcMemory, label->self()->hfont);
|
||||
DrawText(hdcMemory, text, -1, &rc, DT_CALCRECT | DT_END_ELLIPSIS);
|
||||
uint height = rc.bottom;
|
||||
|
||||
GetClientRect(hwnd, &rc);
|
||||
rc.top = (rc.bottom - height) / 2;
|
||||
rc.bottom = rc.top + height;
|
||||
|
@ -67,7 +86,15 @@ static auto CALLBACK Label_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
|
|||
uint verticalAlignment = DT_VCENTER;
|
||||
if(label->alignment().vertical() < 0.333) verticalAlignment = DT_TOP;
|
||||
if(label->alignment().vertical() > 0.666) verticalAlignment = DT_BOTTOM;
|
||||
DrawText(ps.hdc, text, -1, &rc, DT_END_ELLIPSIS | horizontalAlignment | verticalAlignment);
|
||||
if(auto color = label->foregroundColor()) {
|
||||
SetTextColor(hdcMemory, CreateRGB(color));
|
||||
}
|
||||
DrawText(hdcMemory, text, -1, &rc, DT_END_ELLIPSIS | horizontalAlignment | verticalAlignment);
|
||||
|
||||
GetClientRect(hwnd, &rc);
|
||||
BitBlt(ps.hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hdcMemory, 0, 0, SRCCOPY);
|
||||
DeleteObject(hbmMemory);
|
||||
DeleteObject(hdcMemory);
|
||||
EndPaint(hwnd, &ps);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ struct pLabel : pWidget {
|
|||
|
||||
auto minimumSize() const -> Size override;
|
||||
auto setAlignment(Alignment alignment) -> void;
|
||||
auto setBackgroundColor(Color color) -> void;
|
||||
auto setForegroundColor(Color color) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue