Skip to content

Commit

Permalink
Drawing tags in brief and list presentations
Browse files Browse the repository at this point in the history
  • Loading branch information
mikekazakov committed Jan 20, 2024
1 parent a270967 commit dafc04c
Show file tree
Hide file tree
Showing 11 changed files with 167 additions and 54 deletions.
10 changes: 10 additions & 0 deletions Source/NimbleCommander/NimbleCommander/Resources/Config.json
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,16 @@
*/
"ignoreCharacters": " "
},

/**
* Settings related to the usage of Finder Tags
*/
"FinderTags": {
/**
* Enable loading and UI components of tags
*/
"enable": true
},

/**
* Settings related to Spotlight usage
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2016-2022 Michael Kazakov. Subject to GNU General Public License version 3.
// Copyright (C) 2016-2024 Michael Kazakov. Subject to GNU General Public License version 3.
#include "PanelBriefView.h"
#include <VFS/VFS.h>
#include <Base/algo.h>
Expand All @@ -7,6 +7,7 @@
#include <Panel/PanelDataSortMode.h>
#include "../PanelView.h"
#include <Panel/UI/PanelViewPresentationItemsColoringFilter.h>
#include <Panel/UI/TagsPresentation.h>
#include <NimbleCommander/Bootstrap/AppDelegate.h>
#include <NimbleCommander/Bootstrap/Config.h>
#include <NimbleCommander/Core/Theming/Theme.h>
Expand Down Expand Up @@ -284,9 +285,27 @@ - (NSCollectionViewItem *)collectionView:(NSCollectionView *)collectionView
return strings;
}

static void PadWithSpaceForTags(std::span<unsigned short> _widths, const data::Model *_data)
{
if( _data == nullptr )
return;
const auto &sorted_idices = _data->SortedDirectoryEntries();
const auto &listing = _data->Listing();
assert(sorted_idices.size() == _widths.size());
const auto count = static_cast<int>(sorted_idices.size());
for( int i = 0; i < count; ++i ) {
const auto raw_idx = sorted_idices[i];
if(const auto tags = listing.Tags(raw_idx); !tags.empty() ) {
const auto geom = TrailingTagsInplaceDisplay::Place(tags);
_widths[i] += geom.margin + geom.width;
}
}
}

- (void)calculateFilenamesWidths
{
Log::Trace(SPDLOC, "[PanelBriefView calculateFilenamesWidths]");
Log::Trace(SPDLOC, "[PanelBriefView calculateFilenamesWidths] started");
at_scope_end([]{Log::Trace(SPDLOC, "[PanelBriefView calculateFilenamesWidths] finished");});
const auto strings = GatherDisplayFilenames(m_Data);
const auto count = static_cast<int>(strings.size());

Expand All @@ -297,6 +316,7 @@ - (void)calculateFilenamesWidths

const auto font = nc::CurrentTheme().FilePanelsBriefFont();
auto widths = TextWidthsCache::Instance().Widths(strings, font);
PadWithSpaceForTags(widths, m_Data);
assert(static_cast<int>(widths.size()) == count);

const auto &layout = m_ItemLayout;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2016-2023 Michael Kazakov. Subject to GNU General Public License version 3.
// Copyright (C) 2016-2024 Michael Kazakov. Subject to GNU General Public License version 3.
#include <NimbleCommander/Core/Theming/Theme.h>
#include <Panel/UI/PanelViewPresentationItemsColoringFilter.h>
#include "../PanelView.h"
Expand All @@ -23,7 +23,8 @@ - (void)prepareForReuse
m_VD = data::ItemVolatileData{};
m_PanelActive = false;
[super setSelected:false];
self.carrier.background = nil;
self.carrier.backgroundColor = nil;
self.carrier.tagAccentColor = nil;
self.carrier.qsHighlight = {};
}

Expand Down Expand Up @@ -69,13 +70,11 @@ - (void)setPanelActive:(bool)_active
{
if( m_PanelActive == _active )
return;

m_PanelActive = _active;

if( self.selected ) {
[self updateBackgroundColor];
[self updateForegroundColor];
}

[self updateBackgroundColor];
[self updateForegroundColor];
[self updateAccentColor];
}

- (void)setSelected:(BOOL)selected
Expand All @@ -86,6 +85,7 @@ - (void)setSelected:(BOOL)selected

[self updateBackgroundColor];
[self updateForegroundColor];
[self updateAccentColor];
}

- (NSColor *)selectedBackgroundColor
Expand Down Expand Up @@ -141,25 +141,39 @@ - (void)updateForegroundColor
- (void)updateBackgroundColor
{
if( self.selected ) {
self.carrier.background = self.selectedBackgroundColor;
self.carrier.backgroundColor = self.selectedBackgroundColor;
}
else {
if( m_VD.is_selected() ) {
self.carrier.background = nc::CurrentTheme().FilePanelsBriefSelectedItemBackgroundColor();
self.carrier.backgroundColor = nc::CurrentTheme().FilePanelsBriefSelectedItemBackgroundColor();
}
else {
self.carrier.background = nil;
self.carrier.backgroundColor = nil;
}
}
}

- (void)updateAccentColor
{
if( !m_Item )
return;

if( m_PanelActive && m_Item.HasTags() && (m_VD.is_selected() || self.selected) ) {
self.carrier.tagAccentColor = NSColor.whiteColor; // TODO: Pick from Themes
}
else {
self.carrier.tagAccentColor = nil;
}
}

- (void)setVD:(data::ItemVolatileData)_vd
{
if( m_VD == _vd )
return;
m_VD = _vd;
[self updateForegroundColor];
[self updateBackgroundColor];
[self updateAccentColor];
self.carrier.qsHighlight = _vd.highlight;
self.carrier.highlighted = _vd.is_highlighted();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2016-2023 Michael Kazakov. Subject to GNU General Public License version 3.
// Copyright (C) 2016-2024 Michael Kazakov. Subject to GNU General Public License version 3.
#pragma once

#include <Panel/PanelDataItemVolatileData.h>
Expand All @@ -10,7 +10,8 @@ struct PanelBriefViewItemLayoutConstants;
@interface PanelBriefViewItemCarrier : NSView

@property (nonatomic, weak) PanelBriefViewItem *controller;
@property (nonatomic) NSColor *background;
@property (nonatomic) NSColor *backgroundColor;
@property (nonatomic) NSColor *tagAccentColor;
@property (nonatomic) NSString *filename;
@property (nonatomic) NSColor *filenameColor;
@property (nonatomic) NSImage *icon;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2016-2023 Michael Kazakov. Subject to GNU General Public License version 3.
// Copyright (C) 2016-2024 Michael Kazakov. Subject to GNU General Public License version 3.
#include <Utility/FontExtras.h>
#include <NimbleCommander/Core/Theming/Theme.h>
#include "../PanelView.h"
Expand All @@ -8,6 +8,7 @@
#include "PanelBriefViewItemCarrier.h"
#include <Base/dispatch_cpp.h>
#include <Panel/PanelViewFieldEditor.h>
#include <Panel/UI/TagsPresentation.h>

using namespace nc::panel;

Expand Down Expand Up @@ -51,7 +52,8 @@
}

@implementation PanelBriefViewItemCarrier {
NSColor *m_Background;
NSColor *m_BackgroundColor;
NSColor *m_TagAccentColor;
NSColor *m_TextColor;
NSString *m_Filename;
NSImage *m_Icon;
Expand All @@ -65,7 +67,8 @@ @implementation PanelBriefViewItemCarrier {
bool m_IsSymlink;
}

@synthesize background = m_Background;
@synthesize backgroundColor = m_BackgroundColor;
@synthesize tagAccentColor = m_TagAccentColor;
@synthesize filename = m_Filename;
@synthesize layoutConstants = m_LayoutConstants;
@synthesize controller = m_Controller;
Expand Down Expand Up @@ -132,30 +135,43 @@ - (NSRect)calculateTextSegmentFromBounds:(NSRect)bounds
{
const int origin = m_LayoutConstants.icon_size ? 2 * m_LayoutConstants.inset_left + m_LayoutConstants.icon_size
: m_LayoutConstants.inset_left;
const auto width = bounds.size.width - origin - m_LayoutConstants.inset_right;

const auto tags = m_Controller.item.Tags();
const auto tags_geom = TrailingTagsInplaceDisplay::Place(tags);
const auto width = bounds.size.width - origin - m_LayoutConstants.inset_right - tags_geom.margin - tags_geom.width;
return NSMakeRect(origin, 0, width, bounds.size.height);
}

- (void)drawDefaultBackgroundWithBounds:(NSRect)bounds inContext:(CGContextRef)context
static NSColor *Blend(NSColor *_front, NSColor *_back)
{
const bool is_odd = int(self.frame.origin.y / bounds.size.height) % 2;
auto c = is_odd ? nc::CurrentTheme().FilePanelsBriefRegularOddRowBackgroundColor()
: nc::CurrentTheme().FilePanelsBriefRegularEvenRowBackgroundColor();
CGContextSetFillColorWithColor(context, c.CGColor);
CGContextFillRect(context, bounds);
const auto alpha = _front.alphaComponent;
if( alpha == 1. )
return _front;
if( alpha == 0. )
return _back;

const auto cs = NSColorSpace.genericRGBColorSpace;
_front = [_front colorUsingColorSpace:cs];
_back = [_back colorUsingColorSpace:cs];
const auto r = _front.redComponent * alpha + _back.redComponent * (1. - alpha);
const auto g = _front.greenComponent * alpha + _back.greenComponent * (1. - alpha);
const auto b = _front.blueComponent * alpha + _back.blueComponent * (1. - alpha);
return [NSColor colorWithCalibratedRed:r green:g blue:b alpha:1.];
}

- (void)drawCustomBackgroundWithBounds:(NSRect)bounds inContext:(CGContextRef)context
- (NSColor *)deduceBackground:(NSRect)_bounds
{
const auto alpha = m_Background.alphaComponent;

if( alpha != 1. )
[self drawDefaultBackgroundWithBounds:bounds inContext:context];
const bool is_odd = int(self.frame.origin.y / _bounds.size.height) % 2;
auto c = is_odd ? nc::CurrentTheme().FilePanelsBriefRegularOddRowBackgroundColor()
: nc::CurrentTheme().FilePanelsBriefRegularEvenRowBackgroundColor();

if( alpha != 0. ) {
CGContextSetFillColorWithColor(context, m_Background.CGColor);
CGContextFillRect(context, bounds);
if( m_BackgroundColor ) {
const auto alpha = m_BackgroundColor.alphaComponent;
if( alpha == 1. )
return m_BackgroundColor;
return Blend(m_BackgroundColor, c);
}
else {
return c;
}
}

Expand All @@ -164,10 +180,9 @@ - (void)drawRect:(NSRect) [[maybe_unused]] _dirty_rect
const auto bounds = self.bounds;
const auto context = NSGraphicsContext.currentContext.CGContext;

if( m_Background )
[self drawCustomBackgroundWithBounds:bounds inContext:context];
else
[self drawDefaultBackgroundWithBounds:bounds inContext:context];
NSColor *background = [self deduceBackground:bounds];
CGContextSetFillColorWithColor(context, background.CGColor);
CGContextFillRect(context, bounds);

const auto grid_color = nc::CurrentTheme().FilePanelsBriefGridColor();
CGContextSetFillColorWithColor(context, grid_color.CGColor);
Expand Down Expand Up @@ -199,6 +214,15 @@ - (void)drawRect:(NSRect) [[maybe_unused]] _dirty_rect
fraction:1.0
respectFlipped:false
hints:nil];

if( const auto tags = m_Controller.item.Tags(); !tags.empty() ) {
const auto tags_geom = TrailingTagsInplaceDisplay::Place(tags);
TrailingTagsInplaceDisplay::Draw(text_segment_rect.origin.x + text_segment_rect.size.width + tags_geom.margin,
bounds.size.height,
tags,
m_TagAccentColor,
background);
}
}

- (BOOL)acceptsFirstMouse:(NSEvent *) [[maybe_unused]] _event
Expand Down Expand Up @@ -332,10 +356,10 @@ - (void)setFilenameColor:(NSColor *)filenameColor
}
}

- (void)setBackground:(NSColor *)background
- (void)setBackgroundColor:(NSColor *)background
{
if( m_Background != background ) {
m_Background = background;
if( m_BackgroundColor != background ) {
m_BackgroundColor = background;
[self setNeedsDisplay:true];
}
}
Expand Down Expand Up @@ -383,7 +407,9 @@ - (void)setQsHighlight:(nc::panel::data::QuickSearchHiglight)qsHighlight
for( size_t i = 0; i != hl.count; ++i ) {
if( hl.segments[i].offset < fn_len && hl.segments[i].offset + hl.segments[i].length <= fn_len ) {
const auto range = NSMakeRange(hl.segments[i].offset, hl.segments[i].length);
[m_AttrString addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:range];
[m_AttrString addAttribute:NSUnderlineStyleAttributeName
value:@(NSUnderlineStyleSingle)
range:range];
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2016-2023 Michael Kazakov. Subject to GNU General Public License version 3.
// Copyright (C) 2016-2024 Michael Kazakov. Subject to GNU General Public License version 3.
#include "PanelListView.h"
#include <Base/algo.h>
#include <NimbleCommander/Bootstrap/AppDelegate.h>
Expand Down Expand Up @@ -490,7 +490,7 @@ - (void)fillDataForNameView:(PanelListViewNameView *)_view
withItem:(const VFSListingItem &)_item
andVD:(data::ItemVolatileData &)_vd
{
[_view setFilename:_item.DisplayNameNS()];
[_view setFilename:_item.DisplayNameNS() andTags:_item.Tags()];

if( m_IconRepository->IsValidSlot(_vd.icon) == true ) {
[_view setIcon:m_IconRepository->AvailableIconForSlot(_vd.icon)];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
// Copyright (C) 2016-2022 Michael Kazakov. Subject to GNU General Public License version 3.
// Copyright (C) 2016-2024 Michael Kazakov. Subject to GNU General Public License version 3.
#pragma once

#include <Cocoa/Cocoa.h>
#include <Utility/Tags.h>
#include <span>

@class NCPanelViewFieldEditor;

@interface PanelListViewNameView : NSView

@property (nonatomic) NSImage *icon;

- (void) setFilename:(NSString*)_filename;
- (void) setFilename:(NSString*)_filename andTags:(std::span<const nc::utility::Tags::Tag>)_tags;

- (void) buildPresentation;

Expand Down
Loading

0 comments on commit dafc04c

Please sign in to comment.