yacreader/custom_widgets/yacreader_macosx_toolbar.mm
2019-05-30 19:46:37 +02:00

382 lines
12 KiB
Plaintext

#include "yacreader_macosx_toolbar.h"
#include <QWidget>
#include <QMacNativeWidget>
#include <qmacfunctions.h>
#include <qpa/qplatformnativeinterface.h>
#include <QsLog.h>
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#import "shortcuts_manager.h"
//----------------------------
//A custom items separator for NSToolbar
@interface CustomSeparator : NSView
@end
@implementation CustomSeparator
- (void)drawRect:(NSRect)rect
{
[[NSColor colorWithDeviceRed:0.5 green:0.5 blue:0.5 alpha:1] setFill];
NSRectFill(rect);
[super drawRect:rect];
}
@end
//----------------------------
//Toolbar delegate, needed for allow disabled/enabled items
@interface MyToolbarDelegate : NSObject <NSToolbarDelegate> {
@public
YACReaderMacOSXToolbar *mytoolbar;
}
- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdent willBeInsertedIntoToolbar:(BOOL)willBeInserted;
- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar;
- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar;
//- (NSArray *)toolbarSelectableItemIdentifiers:(NSToolbar *)toolbar;
- (IBAction)itemClicked:(id)sender;
- (BOOL)validateToolbarItem:(NSToolbarItem *)theItem;
@end
@implementation MyToolbarDelegate
- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar
{
Q_UNUSED(toolbar);
NSMutableArray *array = [[NSMutableArray alloc] init];
QList<QMacToolBarItem *> items = mytoolbar->items();
foreach (const QMacToolBarItem *item, items) {
[array addObject:item->nativeToolBarItem().itemIdentifier];
}
return array;
}
- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar
{
Q_UNUSED(toolbar);
NSMutableArray *array = [[NSMutableArray alloc] init];
QList<QMacToolBarItem *> items = mytoolbar->items();
foreach (const QMacToolBarItem *item, items) {
[array addObject:item->nativeToolBarItem().itemIdentifier];
}
return array;
}
/*
- (NSArray *)toolbarSelectableItemIdentifiers: (NSToolbar *)toolbar
{
Q_UNUSED(toolbar);
NSMutableArray *array = [[NSMutableArray alloc] init];
QList<QMacToolBarItem *> items = mytoolbar->items();
foreach (const QMacToolBarItem * item, items) {
[array addObject : item->nativeToolBarItem().itemIdentifier];
}
return array;
//NSMutableArray *array = toolbarPrivate->getItemIdentifiers(toolbarPrivate->items, true);
//[array addObjectsFromArray:toolbarPrivate->getItemIdentifiers(toolbarPrivate->allowedItems, true)];
//return array;
}*/
- (IBAction)itemClicked:(id)sender
{
if ([sender respondsToSelector:@selector(itemIdentifier)]) {
NSToolbarItem *item = reinterpret_cast<NSToolbarItem *>(sender);
QString identifier = QString::fromNSString([item itemIdentifier]);
QMacToolBarItem *toolButton = reinterpret_cast<QMacToolBarItem *>(identifier.toULongLong());
Q_EMIT toolButton->activated();
}
}
- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)willBeInserted
{
Q_UNUSED(toolbar);
Q_UNUSED(willBeInserted);
QList<QMacToolBarItem *> items = mytoolbar->items();
foreach (const QMacToolBarItem *item, items) {
NSToolbarItem *toolbarItem = item->nativeToolBarItem();
if ([toolbarItem.itemIdentifier isEqual:itemIdentifier]) {
[toolbarItem setTarget:self];
[toolbarItem setAction:@selector(itemClicked:)];
return toolbarItem;
}
}
return nil;
}
- (BOOL)validateToolbarItem:(NSToolbarItem *)theItem
{
QString identifier = QString::fromNSString(theItem.itemIdentifier);
if (mytoolbar->actions.contains(identifier)) {
return mytoolbar->actions.value(identifier)->isEnabled();
} else
return NO;
}
@end
//----------------------------
//detect changes in native text field
//TODO implement validation and auto completion
@interface MyTextFieldDelegate : NSObject <NSTextFieldDelegate> {
@public
YACReaderMacOSXSearchLineEdit *mylineedit;
}
@end
@implementation MyTextFieldDelegate
- (void)controlTextDidChange:(NSNotification *)notification
{
NSTextField *textField = [notification object];
NSLog(@"%@", [textField stringValue]);
Q_EMIT mylineedit->filterChanged(YACReader::NoModifiers, QString::fromNSString([textField stringValue]));
}
@end
//----------------------------
YACReaderMacOSXToolbar::YACReaderMacOSXToolbar(QObject *parent)
: viewSelector(0)
{
//setup native toolbar
nativeToolBar = nativeToolbar();
[nativeToolBar setDisplayMode:NSToolbarDisplayModeIconOnly];
[nativeToolBar setAllowsUserCustomization:NO];
delegate = [[MyToolbarDelegate alloc] init];
((MyToolbarDelegate *)delegate)->mytoolbar = this;
[nativeToolBar setDelegate:(MyToolbarDelegate *)delegate];
#ifdef YACREADER_LIBRARY
NSWindow *nswindow = (NSWindow *)qApp->platformNativeInterface()->nativeResourceForWindow("nswindow", ((QMainWindow *)parent)->windowHandle());
if ([nswindow respondsToSelector:@selector(setTitleVisibility:)]) {
yosemite = true;
//TODO yosemite new constants are not found in compilation time
[nswindow setTitleVisibility:NSWindowTitleHidden];
//TODO NSFullSizeContentViewWindowMask produces an offset in the windows' content
//nswindow.styleMask |= 1 << 15; // NSFullSizeContentViewWindowMask;
[nativeToolBar setSizeMode:NSToolbarSizeModeSmall]; //TODO figure out how to load specific images in Yosemite
} else {
[nativeToolBar setSizeMode:NSToolbarSizeModeSmall];
yosemite = false;
}
#else
yosemite = false;
[nativeToolBar setAutosavesConfiguration:YES]; //TODO this doesn't work
[nativeToolBar setSizeMode:NSToolbarSizeModeSmall];
#endif
}
void YACReaderMacOSXToolbar::addAction(QAction *action)
{
QMacToolBarItem *toolBarItem = addItem(action->icon(), action->text());
if (action->data().toString() == TOGGLE_COMICS_VIEW_ACTION_YL)
viewSelector = toolBarItem;
connect(toolBarItem, SIGNAL(activated()), action, SIGNAL(triggered()));
NSToolbarItem *nativeItem = toolBarItem->nativeToolBarItem();
actions.insert(QString::fromNSString(nativeItem.itemIdentifier), action);
MacToolBarItemWrapper *wrapper = new MacToolBarItemWrapper(action, toolBarItem);
//wrapper->actionToogled(true);
}
void YACReaderMacOSXToolbar::addDropDownItem(const QList<QAction *> &actions, const QAction *defaultAction)
{
//TODO
}
void YACReaderMacOSXToolbar::addSpace(int size)
{
QMacToolBarItem *toolBarItem = addItem(QIcon(), "");
NSToolbarItem *nativeItem = toolBarItem->nativeToolBarItem();
static const NSRect frameRect = { { 0.0, 0.0 }, { CGFloat(size), 16.0 } };
NSView *view = [[NSView alloc] initWithFrame:frameRect];
[nativeItem setView:view];
}
//reimplemented for convenience
void YACReaderMacOSXToolbar::addSeparator()
{
//QMacToolBar::addSeparator();
QMacToolBarItem *toolBarItem = addItem(QIcon(), "");
NSToolbarItem *nativeItem = toolBarItem->nativeToolBarItem();
static const NSRect frameRect = { { 0.0, 0.0 }, { 1, 16.0 } };
CustomSeparator *view = [[CustomSeparator alloc] initWithFrame:frameRect];
[nativeItem setView:view];
}
void YACReaderMacOSXToolbar::addStretch()
{
QMacToolBarItem *toolBarItem = addItem(QIcon(), "");
toolBarItem->setStandardItem(QMacToolBarItem::FlexibleSpace);
}
void YACReaderMacOSXToolbar::addWidget(QWidget *widget)
{
//TODO fix it
/* QMacNativeWidget *nativeWidget = new QMacNativeWidget();
QVBoxLayout *layout = new QVBoxLayout();
layout->addWidget(widget);
nativeWidget->setLayout(layout);
NSView *nativeWidgetView = reinterpret_cast<NSView *>(nativeWidget->winId());
QMacToolBarItem *toolBarItem = addItem(QIcon(),"");
NSToolbarItem * nativeItem = toolBarItem->nativeToolBarItem();
[nativeItem setView:nativeWidgetView];*/
}
void YACReaderMacOSXToolbar::show()
{
[nativeToolBar setVisible:YES];
}
void YACReaderMacOSXToolbar::hide()
{
[nativeToolBar setVisible:NO];
}
YACReaderMacOSXSearchLineEdit *YACReaderMacOSXToolbar::addSearchEdit()
{
QMacToolBarItem *toolBarItem = addItem(QIcon(), "");
NSToolbarItem *nativeItem = toolBarItem->nativeToolBarItem();
YACReaderMacOSXSearchLineEdit *searchEdit = new YACReaderMacOSXSearchLineEdit();
if (yosemite)
[nativeItem setView:(NSTextField *)searchEdit->getNSTextField()];
else {
static const NSRect searchEditFrameRect = { { 0.0, 0.0 }, { 165, 26.0 } };
NSView *view = [[NSView alloc] initWithFrame:searchEditFrameRect];
[view addSubview:((NSTextField *)searchEdit->getNSTextField())];
[nativeItem setView:view];
}
return searchEdit;
}
//deprecated
QAction *YACReaderMacOSXToolbar::addFitToWidthSlider(QAction *attachToAction)
{
QMacToolBarItem *toolBarItem = addItem(QIcon(":/images/viewer_toolbar/toWidthSlider.png"), "fit to width slider");
NSToolbarItem *nativeItem = toolBarItem->nativeToolBarItem();
actions.insert(QString::fromNSString(nativeItem.itemIdentifier), attachToAction);
QAction *action = new QAction("", attachToAction->parent());
connect(toolBarItem, SIGNAL(activated()), action, SIGNAL(triggered()));
return action;
}
void YACReaderMacOSXToolbar::updateViewSelectorIcon(const QIcon &icon)
{
if (viewSelector)
viewSelector->setIcon(icon);
}
YACReaderMacOSXSearchLineEdit::YACReaderMacOSXSearchLineEdit()
: QObject()
{
NSRect searchEditFrameRect = { { 0.0, -3.0 }, { 165, 32.0 } };
//NSTextField * searchEdit = [[NSTextField alloc] initWithFrame:searchEditFrameRect];
NSTextField *searchEdit = [[NSSearchField alloc] initWithFrame:searchEditFrameRect];
//[searchEdit setBezelStyle:NSTextFieldRoundedBezel];
[[searchEdit cell] setPlaceholderString:@"type to search"];
MyTextFieldDelegate *delegate = [[MyTextFieldDelegate alloc] init];
delegate->mylineedit = this;
[searchEdit setDelegate:delegate];
nstextfield = searchEdit;
}
void *YACReaderMacOSXSearchLineEdit::getNSTextField()
{
return nstextfield;
}
QString YACReaderMacOSXSearchLineEdit::text()
{
return QString::fromNSString([((NSTextField *)nstextfield) stringValue]);
}
void YACReaderMacOSXSearchLineEdit::clear()
{
[((NSTextField *)nstextfield) setStringValue:@""];
emit filterChanged(YACReader::NoModifiers, "");
}
void YACReaderMacOSXSearchLineEdit::clearText()
{
//TODO be sure that this will not generate any event....
[((NSTextField *)nstextfield) setStringValue:@""];
}
void YACReaderMacOSXSearchLineEdit::setDisabled(bool disabled)
{
[((NSTextField *)nstextfield) setEnabled:!disabled];
}
void YACReaderMacOSXSearchLineEdit::setEnabled(bool enabled)
{
[((NSTextField *)nstextfield) setEnabled:enabled];
}
MacToolBarItemWrapper::MacToolBarItemWrapper(QAction *action, QMacToolBarItem *toolbaritem)
: action(action), toolbaritem(toolbaritem)
{
if (action->isCheckable()) {
connect(action, SIGNAL(toggled(bool)), this, SLOT(actionToggled(bool)));
connect(toolbaritem, SIGNAL(activated()), action, SLOT(toggle()));
updateIcon(action->isChecked());
}
}
void MacToolBarItemWrapper::actionToggled(bool toogled)
{
updateIcon(toogled);
}
void MacToolBarItemWrapper::updateIcon(bool enabled)
{
if (enabled) {
QIcon icon = action->icon();
QPixmap tempPixmap = icon.pixmap(QSize(24, 24));
QPainter painter;
painter.begin(&tempPixmap);
painter.fillRect(QRect(3, 21, 18, 1), QColor("#3F3F3F"));
painter.fillRect(QRect(3, 22, 18, 1), QColor("#6E6E6E"));
painter.fillRect(QRect(3, 23, 18, 1), QColor("#EEEEEE"));
painter.end();
toolbaritem->setIcon(QIcon(tempPixmap));
} else
toolbaritem->setIcon(action->icon());
}