Skip to content

Commit 7c7660b

Browse files
committed
Add a visual indication for the defaults in the encoding/collation menus in table structure view (final part of #2237)
1 parent f02fb78 commit 7c7660b

File tree

5 files changed

+316
-2
lines changed

5 files changed

+316
-2
lines changed

Interfaces/English.lproj/DBView.xib

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1675,7 +1675,7 @@
16751675
<nil key="NSMenuItem"/>
16761676
<bool key="NSMenuItemRespectAlignment">YES</bool>
16771677
<object class="NSMenu" key="NSMenu" id="856601787">
1678-
<string key="NSTitle">OtherViews</string>
1678+
<string key="NSTitle">encodingPopupMenu</string>
16791679
<array class="NSMutableArray" key="NSMenuItems"/>
16801680
</object>
16811681
<int key="NSSelectedIndex">-1</int>
@@ -1717,7 +1717,7 @@
17171717
<nil key="NSMenuItem"/>
17181718
<bool key="NSMenuItemRespectAlignment">YES</bool>
17191719
<object class="NSMenu" key="NSMenu" id="65801928">
1720-
<string key="NSTitle">OtherViews</string>
1720+
<string key="NSTitle">collationPopupMenu</string>
17211721
<array class="NSMutableArray" key="NSMenuItems"/>
17221722
</object>
17231723
<int key="NSSelectedIndex">-1</int>
@@ -17350,6 +17350,22 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes>
1735017350
</object>
1735117351
<string key="id">7299</string>
1735217352
</object>
17353+
<object class="IBConnectionRecord">
17354+
<object class="IBOutletConnection" key="connection">
17355+
<string key="label">delegate</string>
17356+
<reference key="source" ref="856601787"/>
17357+
<reference key="destination" ref="239767357"/>
17358+
</object>
17359+
<string key="id">Jbs-NM-Lzb</string>
17360+
</object>
17361+
<object class="IBConnectionRecord">
17362+
<object class="IBOutletConnection" key="connection">
17363+
<string key="label">delegate</string>
17364+
<reference key="source" ref="65801928"/>
17365+
<reference key="destination" ref="239767357"/>
17366+
</object>
17367+
<string key="id">Dcc-ay-7AU</string>
17368+
</object>
1735317369
<object class="IBConnectionRecord">
1735417370
<object class="IBOutletConnection" key="connection">
1735517371
<string key="label">delegate</string>

Source/SPPillAttachmentCell.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//
2+
// SPPillAttachmentCell.h
3+
// sequel-pro
4+
//
5+
// Created by Max Lohrmann on 01.11.15.
6+
// Copyright (c) 2015 Max Lohrmann. All rights reserved.
7+
//
8+
// Permission is hereby granted, free of charge, to any person
9+
// obtaining a copy of this software and associated documentation
10+
// files (the "Software"), to deal in the Software without
11+
// restriction, including without limitation the rights to use,
12+
// copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
// copies of the Software, and to permit persons to whom the
14+
// Software is furnished to do so, subject to the following
15+
// conditions:
16+
//
17+
// The above copyright notice and this permission notice shall be
18+
// included in all copies or substantial portions of the Software.
19+
//
20+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22+
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24+
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25+
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26+
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27+
// OTHER DEALINGS IN THE SOFTWARE.
28+
//
29+
// More info at <https://github.com/sequelpro/sequelpro>
30+
31+
#import <Foundation/Foundation.h>
32+
33+
/**
34+
* This is a simple TextAttachmentCell which takes the stringValue
35+
* and displays it in a "pill", much like the tokens in an NSTokenTextField.
36+
*
37+
* It is designed to be used with static labels rather than inside user input text fields.
38+
*
39+
* To use it:
40+
*
41+
* NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
42+
* SPPillAttachmentCell *cell = [[SPPillAttachmentCell alloc] init];
43+
* [cell setStringValue:@"..."];
44+
* [attachment setAttachmentCell:[cell autorelease];
45+
* NSAttributedString *att = [NSAttributedString attributedStringWithAttachment:[attachment autorelease]];
46+
* [otherAttributedString appendAttributedString:att];
47+
*
48+
*/
49+
@interface SPPillAttachmentCell : NSTextAttachmentCell {
50+
NSColor *_borderColor;
51+
NSGradient *_gradient;
52+
}
53+
@end

Source/SPPillAttachmentCell.m

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
//
2+
// SPPillAttachmentCell.m
3+
// sequel-pro
4+
//
5+
// Created by Max Lohrmann on 01.11.15.
6+
// Copyright (c) 2015 Max Lohrmann. All rights reserved.
7+
//
8+
// Permission is hereby granted, free of charge, to any person
9+
// obtaining a copy of this software and associated documentation
10+
// files (the "Software"), to deal in the Software without
11+
// restriction, including without limitation the rights to use,
12+
// copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
// copies of the Software, and to permit persons to whom the
14+
// Software is furnished to do so, subject to the following
15+
// conditions:
16+
//
17+
// The above copyright notice and this permission notice shall be
18+
// included in all copies or substantial portions of the Software.
19+
//
20+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22+
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24+
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25+
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26+
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27+
// OTHER DEALINGS IN THE SOFTWARE.
28+
//
29+
// More info at <https://github.com/sequelpro/sequelpro>
30+
31+
#import "SPPillAttachmentCell.h"
32+
33+
34+
@implementation SPPillAttachmentCell
35+
36+
- (id)init
37+
{
38+
if(self = [super init]) {
39+
_borderColor = [[NSColor colorWithCalibratedRed:168/255.0 green:184/255.0 blue:249/255.0 alpha: 1] retain];
40+
_gradient = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithCalibratedRed:199/255.0 green:216/255.0 blue:244/255.0 alpha: 1]
41+
endingColor:[NSColor colorWithCalibratedRed:217/255.0 green:229/255.0 blue:247/255.0 alpha: 1]];
42+
}
43+
return self;
44+
}
45+
46+
- (void)dealloc
47+
{
48+
SPClear(_borderColor);
49+
SPClear(_gradient);
50+
51+
[super dealloc];
52+
}
53+
54+
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
55+
{
56+
[self drawWithFrame:cellFrame inView:controlView characterIndex:NSNotFound];
57+
}
58+
59+
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView characterIndex:(NSUInteger)charIndex
60+
{
61+
[self drawWithFrame:cellFrame inView:controlView characterIndex:charIndex layoutManager:nil];
62+
}
63+
64+
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView characterIndex:(NSUInteger)charIndex layoutManager:(NSLayoutManager *)layoutManager
65+
{
66+
CGFloat bRadius = cellFrame.size.height/2.0;
67+
NSBezierPath* rectanglePath = [NSBezierPath bezierPathWithRoundedRect:NSInsetRect(cellFrame,1,1) xRadius:bRadius yRadius:bRadius];
68+
[_gradient drawInBezierPath: rectanglePath angle: -90];
69+
[_borderColor setStroke];
70+
[rectanglePath setLineWidth:1.0];
71+
[rectanglePath stroke];
72+
73+
[self drawInteriorWithFrame:cellFrame inView:controlView];
74+
}
75+
76+
- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
77+
{
78+
NSString* textContent = [self stringValue];
79+
NSMutableParagraphStyle* rectangleStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
80+
[rectangleStyle setAlignment:NSCenterTextAlignment];
81+
82+
NSMutableDictionary *rectangleFontAttributes = [NSMutableDictionary dictionaryWithDictionary:[self attributes]];
83+
[rectangleFontAttributes setObject:[rectangleStyle autorelease] forKey:NSParagraphStyleAttributeName];
84+
85+
//cellFrame.origin.y += [[self font] descender];
86+
[textContent drawInRect:cellFrame withAttributes:rectangleFontAttributes];
87+
}
88+
89+
- (NSPoint)cellBaselineOffset
90+
{
91+
//Not used in menu
92+
return NSMakePoint(0, [[self font] descender]-1);
93+
}
94+
95+
- (NSRect)cellFrameForTextContainer:(NSTextContainer *)textContainer proposedLineFragment:(NSRect)lineFrag glyphPosition:(NSPoint)position characterIndex:(NSUInteger)charIndex
96+
{
97+
NSSize sz = [self cellSize];
98+
CGFloat offset = (lineFrag.size.height - sz.height) / 2;
99+
return NSMakeRect(0, [[self font] descender]+offset, sz.width+(2*12), sz.height);
100+
}
101+
102+
- (NSSize)cellSize
103+
{
104+
//Not used in menu
105+
return [[self stringValue] sizeWithAttributes:[self attributes]];
106+
}
107+
108+
- (NSDictionary *)attributes
109+
{
110+
return @{NSFontAttributeName: [self font],NSForegroundColorAttributeName: [NSColor controlTextColor]};
111+
}
112+
113+
@end

Source/SPTableStructureDelegate.m

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,27 @@
3838
#import "SPTableStructureLoading.h"
3939
#import "SPServerSupport.h"
4040
#import "SPTablesList.h"
41+
#import "SPPillAttachmentCell.h"
4142

4243
#import <SPMySQL/SPMySQL.h>
4344

45+
struct _cmpMap {
46+
NSString *title; // the title of the "pill"
47+
NSString *tooltipPart; // the tooltip of the menuitem
48+
NSString *cmpWith; // the string to match against
49+
};
50+
51+
/**
52+
* This function will compare the representedObject of every item in menu against
53+
* every map->cmpWith. If they match it will append a pill-like (similar to a TokenFieldCell's token)
54+
* element labelled map->title to the menu item's title. If map->tooltipPart is set,
55+
* it will also be added to the menu item's tooltip.
56+
*
57+
* This is used with the encoding/collation popup menus to add visual indicators for the
58+
* table-level and default encoding/collation.
59+
*/
60+
static void _BuildMenuWithPills(NSMenu *menu,struct _cmpMap *map,size_t mapEntries);
61+
4462
@interface SPTableStructure (PrivateAPI)
4563

4664
- (void)sheetDidEnd:(id)sheet returnCode:(NSInteger)returnCode contextInfo:(NSString *)contextInfo;
@@ -69,6 +87,7 @@ - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColum
6987
NSString *columnEncoding = [rowData objectForKey:@"encodingName"];
7088
NSString *columnCollation = [rowData objectForKey:@"collationName"]; // loadTable: has already inferred it, if not set explicit
7189

90+
#warning Building the collation menu here is a big performance hog. This should be done in menuNeedsUpdate: below!
7291
NSPopUpButtonCell *collationCell = [tableColumn dataCell];
7392
[collationCell removeAllItems];
7493
[collationCell addItemWithTitle:@"dummy"];
@@ -698,4 +717,111 @@ - (NSString *)comboBoxCell:(NSComboBoxCell *)aComboBoxCell completedString:(NSSt
698717
return @"";
699718
}
700719

720+
#pragma mark -
721+
#pragma mark Menu delegate methods (encoding/collation dropdown menu)
722+
723+
- (void)menuNeedsUpdate:(NSMenu *)menu
724+
{
725+
//NOTE: NSTableView will usually copy the menu and call this method on the copy. Matching with == won't work!
726+
727+
//walk through the menu and clear the attributedTitle if set. This will remove the gray color from the default items
728+
for(NSMenuItem *item in [menu itemArray]) {
729+
if([item attributedTitle]) {
730+
[item setAttributedTitle:nil];
731+
}
732+
}
733+
734+
NSDictionary *rowData = NSArrayObjectAtIndex(tableFields, [tableSourceView selectedRow]);
735+
736+
if([[menu title] isEqualToString:@"encodingPopupMenu"]) {
737+
NSString *tableEncoding = [tableDataInstance tableEncoding];
738+
//NSString *databaseEncoding = [databaseDataInstance getDatabaseDefaultCharacterSet];
739+
//NSString *serverEncoding = [databaseDataInstance getServerDefaultCharacterSet];
740+
741+
struct _cmpMap defaultCmp[] = {
742+
{
743+
NSLocalizedString(@"Table",@"Table Structure : Encoding dropdown : 'item is table default' marker"),
744+
[NSString stringWithFormat:NSLocalizedString(@"This is the default encoding of table “%@”.", @"Table Structure : Encoding dropdown : table marker tooltip"),selectedTable],
745+
tableEncoding
746+
},
747+
/* //we could, but that might confuse users even more plus there is no inheritance between a columns charset and the db/server default
748+
{
749+
NSLocalizedString(@"Database",@"Table Structure : Encoding dropdown : 'item is database default' marker"),
750+
[NSString stringWithFormat:NSLocalizedString(@"This is the default encoding of database “%@”.", @"Table Structure : Encoding dropdown : database marker tooltip"),[tableDocumentInstance database]],
751+
databaseEncoding
752+
},
753+
{
754+
NSLocalizedString(@"Server",@"Table Structure : Encoding dropdown : 'item is server default' marker"),
755+
NSLocalizedString(@"This is the default encoding of this server.", @"Table Structure : Encoding dropdown : server marker tooltip"),
756+
serverEncoding
757+
} */
758+
};
759+
760+
_BuildMenuWithPills(menu, defaultCmp, COUNT_OF(defaultCmp));
761+
}
762+
else if([[menu title] isEqualToString:@"collationPopupMenu"]) {
763+
NSString *encoding = [rowData objectForKey:@"encodingName"];
764+
NSString *encodingDefaultCollation = [databaseDataInstance getDefaultCollationForEncoding:encoding];
765+
NSString *tableCollation = [tableDataInstance statusValueForKey:@"Collation"];
766+
//NSString *databaseCollation = [databaseDataInstance getDatabaseDefaultCollation];
767+
//NSString *serverCollation = [databaseDataInstance getServerDefaultCollation];
768+
769+
struct _cmpMap defaultCmp[] = {
770+
{
771+
NSLocalizedString(@"Default",@"Table Structure : Collation dropdown : 'item is the same as the default collation of the row's charset' marker"),
772+
[NSString stringWithFormat:NSLocalizedString(@"This is the default collation of encoding “%@”.", @"Table Structure : Collation dropdown : default marker tooltip"),encoding],
773+
encodingDefaultCollation
774+
},
775+
{
776+
NSLocalizedString(@"Table",@"Table Structure : Collation dropdown : 'item is the same as the collation of table' marker"),
777+
[NSString stringWithFormat:NSLocalizedString(@"This is the default collation of table “%@”.", @"Table Structure : Collation dropdown : table marker tooltip"),selectedTable],
778+
tableCollation
779+
},
780+
/* // see the comment for charset above
781+
{
782+
NSLocalizedString(@"Database",@"Table Structure : Collation dropdown : 'item is the same as the collation of database' marker"),
783+
[NSString stringWithFormat:NSLocalizedString(@"This is the default collation of database “%@”.", @"Table Structure : Collation dropdown : database marker tooltip"),[tableDocumentInstance database]],
784+
databaseCollation
785+
},
786+
{
787+
NSLocalizedString(@"Server",@"Table Structure : Collation dropdown : 'item is the same as the collation of server' marker"),
788+
NSLocalizedString(@"This is the default collation of this server.", @"Table Structure : Collation dropdown : server marker tooltip"),
789+
serverCollation
790+
} */
791+
};
792+
793+
_BuildMenuWithPills(menu, defaultCmp, COUNT_OF(defaultCmp));
794+
}
795+
}
796+
701797
@end
798+
799+
void _BuildMenuWithPills(NSMenu *menu,struct _cmpMap *map,size_t mapEntries)
800+
{
801+
NSDictionary *baseAttrs = @{NSFontAttributeName:[menu font],NSParagraphStyleAttributeName: [NSParagraphStyle defaultParagraphStyle]};
802+
803+
for(NSMenuItem *item in [menu itemArray]) {
804+
NSMutableAttributedString *itemStr = [[NSMutableAttributedString alloc] initWithString:[item title] attributes:baseAttrs];
805+
NSString *value = [item representedObject];
806+
807+
NSMutableArray *tooltipParts = [NSMutableArray array];
808+
for (unsigned int i = 0; i < mapEntries; ++i) {
809+
struct _cmpMap *cmp = &map[i];
810+
if([cmp->cmpWith isEqualToString:value]) {
811+
SPPillAttachmentCell *cell = [[SPPillAttachmentCell alloc] init];
812+
[cell setStringValue:cmp->title];
813+
NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
814+
[attachment setAttachmentCell:[cell autorelease]];
815+
NSAttributedString *attachmentString = [NSAttributedString attributedStringWithAttachment:[attachment autorelease]];
816+
817+
[[itemStr mutableString] appendString:@" "];
818+
[itemStr appendAttributedString:attachmentString];
819+
820+
if(cmp->tooltipPart) [tooltipParts addObject:cmp->tooltipPart];
821+
}
822+
}
823+
if([tooltipParts count]) [item setToolTip:[tooltipParts componentsJoinedByString:@" "]];
824+
825+
[item setAttributedTitle:[itemStr autorelease]];
826+
}
827+
}

sequel-pro.xcodeproj/project.pbxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@
155155
17F90E481210B42700274C98 /* SPExportFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 17F90E471210B42700274C98 /* SPExportFile.m */; };
156156
17F90E4B1210B43A00274C98 /* SPExportFileUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 17F90E4A1210B43A00274C98 /* SPExportFileUtilities.m */; };
157157
17FDB04C1280778B00DBBBC2 /* SPFontPreviewTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = 17FDB04B1280778B00DBBBC2 /* SPFontPreviewTextField.m */; };
158+
1A564F74237E2E4958CA593A /* SPPillAttachmentCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A56463D14569A0B56EE8BAC /* SPPillAttachmentCell.m */; };
158159
296DC89F0F8FD336002A3258 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 296DC89E0F8FD336002A3258 /* WebKit.framework */; };
159160
296DC8B60F909194002A3258 /* MGTemplateEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 296DC8A70F909194002A3258 /* MGTemplateEngine.m */; };
160161
296DC8B70F909194002A3258 /* RegexKitLite.m in Sources */ = {isa = PBXBuildFile; fileRef = 296DC8AB0F909194002A3258 /* RegexKitLite.m */; };
@@ -859,6 +860,8 @@
859860
17F90E4A1210B43A00274C98 /* SPExportFileUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPExportFileUtilities.m; sourceTree = "<group>"; };
860861
17FDB04A1280778B00DBBBC2 /* SPFontPreviewTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPFontPreviewTextField.h; sourceTree = "<group>"; };
861862
17FDB04B1280778B00DBBBC2 /* SPFontPreviewTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPFontPreviewTextField.m; sourceTree = "<group>"; };
863+
1A56463D14569A0B56EE8BAC /* SPPillAttachmentCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPPillAttachmentCell.m; sourceTree = "<group>"; };
864+
1A564C0C0FFB444D2E5CA447 /* SPPillAttachmentCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPPillAttachmentCell.h; sourceTree = "<group>"; };
862865
296DC89E0F8FD336002A3258 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = /System/Library/Frameworks/WebKit.framework; sourceTree = "<absolute>"; };
863866
296DC8A50F909194002A3258 /* MGTemplateMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTemplateMarker.h; sourceTree = "<group>"; };
864867
296DC8A60F909194002A3258 /* MGTemplateFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTemplateFilter.h; sourceTree = "<group>"; };
@@ -1441,6 +1444,8 @@
14411444
B57747DB0F7A89D0003B34F9 /* SPFavoriteTextFieldCell.m */,
14421445
BC5750D412A6233900911BA2 /* SPActivityTextFieldCell.h */,
14431446
BC5750D312A6233900911BA2 /* SPActivityTextFieldCell.m */,
1447+
1A56463D14569A0B56EE8BAC /* SPPillAttachmentCell.m */,
1448+
1A564C0C0FFB444D2E5CA447 /* SPPillAttachmentCell.h */,
14441449
);
14451450
name = Cells;
14461451
sourceTree = "<group>";
@@ -3348,6 +3353,7 @@
33483353
501B1D181728A3DA0017C92E /* SPCharsetCollationHelper.m in Sources */,
33493354
50E217B318174246009D3580 /* SPColorSelectorView.m in Sources */,
33503355
50E217B618174280009D3580 /* SPFavoriteColorSupport.m in Sources */,
3356+
1A564F74237E2E4958CA593A /* SPPillAttachmentCell.m in Sources */,
33513357
);
33523358
runOnlyForDeploymentPostprocessing = 0;
33533359
};

0 commit comments

Comments
 (0)