Handle out-of-screen conditions. Improve drawing code.
This commit is contained in:
parent
b492cb1f10
commit
dd43b08d82
|
@ -52,6 +52,8 @@
|
||||||
- (BOOL)highlightNextCandidate;
|
- (BOOL)highlightNextCandidate;
|
||||||
- (BOOL)highlightPreviousCandidate;
|
- (BOOL)highlightPreviousCandidate;
|
||||||
|
|
||||||
|
- (void)setWindowTopLeftPoint:(NSPoint)topLeftPoint bottomOutOfScreenAdjustmentHeight:(CGFloat)height;
|
||||||
|
|
||||||
- (NSUInteger)candidateIndexAtKeyLabelIndex:(NSUInteger)index;
|
- (NSUInteger)candidateIndexAtKeyLabelIndex:(NSUInteger)index;
|
||||||
|
|
||||||
@property (assign, weak, nonatomic) id<VTCandidateControllerDelegate> delegate;
|
@property (assign, weak, nonatomic) id<VTCandidateControllerDelegate> delegate;
|
||||||
|
|
|
@ -82,6 +82,52 @@
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setWindowTopLeftPoint:(NSPoint)topLeftPoint bottomOutOfScreenAdjustmentHeight:(CGFloat)height
|
||||||
|
{
|
||||||
|
NSPoint adjustedPoint = topLeftPoint;
|
||||||
|
CGFloat adjustedHeight = height;
|
||||||
|
|
||||||
|
// first, locate the screen the point is in
|
||||||
|
NSRect screenFrame = [[NSScreen mainScreen] visibleFrame];
|
||||||
|
|
||||||
|
for (NSScreen *screen in [NSScreen screens]) {
|
||||||
|
NSRect frame = [screen visibleFrame];
|
||||||
|
if (topLeftPoint.x >= NSMinX(frame) && topLeftPoint.x <= NSMaxX(frame)) {
|
||||||
|
screenFrame = frame;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure we don't have any erratic value
|
||||||
|
if (adjustedHeight > screenFrame.size.height / 2.0) {
|
||||||
|
adjustedHeight = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSSize windowSize = [[self window] frame].size;
|
||||||
|
|
||||||
|
// bottom beneath the screen?
|
||||||
|
if (adjustedPoint.y - windowSize.height < NSMinY(screenFrame)) {
|
||||||
|
adjustedPoint.y = topLeftPoint.y + adjustedHeight + windowSize.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// top over the screen?
|
||||||
|
if (adjustedPoint.y >= NSMaxY(screenFrame)) {
|
||||||
|
adjustedPoint.y = NSMaxY(screenFrame) - 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// right
|
||||||
|
if (adjustedPoint.x + windowSize.width >= NSMaxX(screenFrame)) {
|
||||||
|
adjustedPoint.x = NSMaxX(screenFrame) - windowSize.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
// left
|
||||||
|
if (adjustedPoint.x < NSMinX(screenFrame)) {
|
||||||
|
adjustedPoint.x = NSMinX(screenFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[self window] setFrameTopLeftPoint:adjustedPoint];
|
||||||
|
}
|
||||||
|
|
||||||
- (NSUInteger)candidateIndexAtKeyLabelIndex:(NSUInteger)index
|
- (NSUInteger)candidateIndexAtKeyLabelIndex:(NSUInteger)index
|
||||||
{
|
{
|
||||||
return NSUIntegerMax;
|
return NSUIntegerMax;
|
||||||
|
@ -108,9 +154,9 @@
|
||||||
return NSMakePoint(frameRect.origin.x, frameRect.origin.y + frameRect.size.height);
|
return NSMakePoint(frameRect.origin.x, frameRect.origin.y + frameRect.size.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setWindowTopLeftPoint:(NSPoint)windowTopLeftPoint
|
- (void)setWindowTopLeftPoint:(NSPoint)topLeftPoint
|
||||||
{
|
{
|
||||||
[[self window] setFrameTopLeftPoint:windowTopLeftPoint];
|
[self setWindowTopLeftPoint:topLeftPoint bottomOutOfScreenAdjustmentHeight:0.0];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSUInteger)selectedCandidateIndex
|
- (NSUInteger)selectedCandidateIndex
|
||||||
|
|
|
@ -192,6 +192,13 @@
|
||||||
NSRect buttonRect = [_nextPageButton frame];
|
NSRect buttonRect = [_nextPageButton frame];
|
||||||
CGFloat spacing = 0.0;
|
CGFloat spacing = 0.0;
|
||||||
|
|
||||||
|
if (newSize.height < 40.0) {
|
||||||
|
buttonRect.size.height = floor(newSize.height / 2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buttonRect.size.height = 20.0;
|
||||||
|
}
|
||||||
|
|
||||||
if (newSize.height >= 60.0) {
|
if (newSize.height >= 60.0) {
|
||||||
spacing = ceil(newSize.height * 0.1);
|
spacing = ceil(newSize.height * 0.1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,10 @@
|
||||||
|
|
||||||
#import "VTHorizontalCandidateView.h"
|
#import "VTHorizontalCandidateView.h"
|
||||||
|
|
||||||
|
// use these instead of MIN/MAX macro to keep compilers happy with pedantic warnings on
|
||||||
|
NS_INLINE CGFloat min(CGFloat a, CGFloat b) { return a < b ? a : b; }
|
||||||
|
NS_INLINE CGFloat max(CGFloat a, CGFloat b) { return a > b ? a : b; }
|
||||||
|
|
||||||
@implementation VTHorizontalCandidateView
|
@implementation VTHorizontalCandidateView
|
||||||
|
|
||||||
@synthesize highlightedIndex = _highlightedIndex;
|
@synthesize highlightedIndex = _highlightedIndex;
|
||||||
|
@ -46,7 +50,7 @@
|
||||||
|
|
||||||
- (void)setKeyLabels:(NSArray *)labels displayedCandidates:(NSArray *)candidates
|
- (void)setKeyLabels:(NSArray *)labels displayedCandidates:(NSArray *)candidates
|
||||||
{
|
{
|
||||||
NSUInteger count = MIN([labels count], [candidates count]);
|
NSUInteger count = min([labels count], [candidates count]);
|
||||||
id tmp;
|
id tmp;
|
||||||
|
|
||||||
tmp = _keyLabels;
|
tmp = _keyLabels;
|
||||||
|
@ -66,7 +70,7 @@
|
||||||
// TODO: Handle CJK text drawing
|
// TODO: Handle CJK text drawing
|
||||||
NSRect candidateRect = [[_displayedCandidates objectAtIndex:index] boundingRectWithSize:baseSize options:NSStringDrawingUsesLineFragmentOrigin attributes:_candidateAttrDict];
|
NSRect candidateRect = [[_displayedCandidates objectAtIndex:index] boundingRectWithSize:baseSize options:NSStringDrawingUsesLineFragmentOrigin attributes:_candidateAttrDict];
|
||||||
|
|
||||||
CGFloat width = MAX(labelRect.size.width, candidateRect.size.width) + _cellPadding;
|
CGFloat width = max(labelRect.size.width, candidateRect.size.width) + _cellPadding;
|
||||||
[newWidths addObject:[NSNumber numberWithDouble:width]];
|
[newWidths addObject:[NSNumber numberWithDouble:width]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,50 +111,12 @@
|
||||||
|
|
||||||
|
|
||||||
CGFloat labelFontSize = [labelFont pointSize];
|
CGFloat labelFontSize = [labelFont pointSize];
|
||||||
CGFloat candidateFontSize = MAX([candidateFont pointSize], [candidateFontCJK pointSize]);
|
CGFloat candidateFontSize = max([candidateFont pointSize], [candidateFontCJK pointSize]);
|
||||||
CGFloat biggestSize = MAX(labelFontSize, candidateFontSize);
|
CGFloat biggestSize = max(labelFontSize, candidateFontSize);
|
||||||
|
|
||||||
_keyLabelHeight = labelFontSize;
|
_keyLabelHeight = ceil(labelFontSize * 1.20);
|
||||||
_candidateTextHeight = candidateFontSize;
|
_candidateTextHeight = ceil(candidateFontSize * 1.20);
|
||||||
|
_cellPadding = ceil(biggestSize / 2.0);
|
||||||
if (labelFontSize <= 16.0) {
|
|
||||||
_keyLabelHeight += 4.0;
|
|
||||||
}
|
|
||||||
else if (labelFontSize <= 24.0) {
|
|
||||||
_keyLabelHeight += 8.0;
|
|
||||||
}
|
|
||||||
else if (labelFontSize <= 64.0) {
|
|
||||||
_keyLabelHeight += 16.0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_keyLabelHeight += 24.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (candidateFontSize <= 16.0) {
|
|
||||||
_candidateTextHeight += 4.0;
|
|
||||||
}
|
|
||||||
else if (candidateFontSize <= 24.0) {
|
|
||||||
_candidateTextHeight += 8.0;
|
|
||||||
}
|
|
||||||
else if (candidateFontSize <= 64.0) {
|
|
||||||
_candidateTextHeight += 16.0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_candidateTextHeight += 24.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (biggestSize <= 16.0) {
|
|
||||||
_cellPadding = 8.0;
|
|
||||||
}
|
|
||||||
else if (biggestSize <= 24.0) {
|
|
||||||
_cellPadding = 16.0;
|
|
||||||
}
|
|
||||||
else if (biggestSize <= 64.0) {
|
|
||||||
_cellPadding = 24.0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_cellPadding = 32.0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,10 @@
|
||||||
#import "VTVerticalKeyLabelStripView.h"
|
#import "VTVerticalKeyLabelStripView.h"
|
||||||
#import "VTVerticalCandidateTableView.h"
|
#import "VTVerticalCandidateTableView.h"
|
||||||
|
|
||||||
|
// use these instead of MIN/MAX macro to keep compilers happy with pedantic warnings on
|
||||||
|
NS_INLINE CGFloat min(CGFloat a, CGFloat b) { return a < b ? a : b; }
|
||||||
|
NS_INLINE CGFloat max(CGFloat a, CGFloat b) { return a > b ? a : b; }
|
||||||
|
|
||||||
static const CGFloat kCandidateTextPadding = 24.0;
|
static const CGFloat kCandidateTextPadding = 24.0;
|
||||||
static const CGFloat kCandidateTextLeftMargin = 8.0;
|
static const CGFloat kCandidateTextLeftMargin = 8.0;
|
||||||
|
|
||||||
|
@ -108,7 +112,7 @@ static const CGFloat kCandidateTextLeftMargin = 8.0;
|
||||||
|
|
||||||
- (void)reloadData
|
- (void)reloadData
|
||||||
{
|
{
|
||||||
_maxCandidateAttrStringWidth = ceil(MAX([_candidateFont pointSize], [_CJKCandidateFont pointSize])) * 2.0 + kCandidateTextPadding;
|
_maxCandidateAttrStringWidth = ceil(max([_candidateFont pointSize], [_CJKCandidateFont pointSize])) * 2.0 + kCandidateTextPadding;
|
||||||
|
|
||||||
[_tableView reloadData];
|
[_tableView reloadData];
|
||||||
[self layoutCandidateView];
|
[self layoutCandidateView];
|
||||||
|
@ -168,7 +172,7 @@ static const CGFloat kCandidateTextLeftMargin = 8.0;
|
||||||
|
|
||||||
if (selectedRow != -1 && itemCount > 0 && itemCount > labelCount) {
|
if (selectedRow != -1 && itemCount > 0 && itemCount > labelCount) {
|
||||||
if (newIndex > selectedRow && (newIndex - selectedRow) > 1) {
|
if (newIndex > selectedRow && (newIndex - selectedRow) > 1) {
|
||||||
lastVisibleRow = MIN(newIndex + labelCount - 1, itemCount - 1);
|
lastVisibleRow = min(newIndex + labelCount - 1, itemCount - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// no need to handle the backward case: (newIndex < selectedRow && selectedRow - newIndex > 1)
|
// no need to handle the backward case: (newIndex < selectedRow && selectedRow - newIndex > 1)
|
||||||
|
@ -274,7 +278,7 @@ static const CGFloat kCandidateTextLeftMargin = 8.0;
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
newIndex = MIN(newIndex + labelCount, itemCount - 1);
|
newIndex = min(newIndex + labelCount, itemCount - 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (newIndex == 0) {
|
if (newIndex == 0) {
|
||||||
|
@ -329,9 +333,9 @@ static const CGFloat kCandidateTextLeftMargin = 8.0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGFloat candidateFontSize = ceil(MAX([_candidateFont pointSize], [_CJKCandidateFont pointSize]));
|
CGFloat candidateFontSize = ceil(max([_candidateFont pointSize], [_CJKCandidateFont pointSize]));
|
||||||
CGFloat keyLabelFontSize = ceil([_keyLabelFont pointSize]);
|
CGFloat keyLabelFontSize = ceil([_keyLabelFont pointSize]);
|
||||||
CGFloat fontSize = MAX(candidateFontSize, keyLabelFontSize);
|
CGFloat fontSize = max(candidateFontSize, keyLabelFontSize);
|
||||||
|
|
||||||
NSControlSize controlSize = (fontSize > 36.0) ? NSRegularControlSize : NSSmallControlSize;
|
NSControlSize controlSize = (fontSize > 36.0) ? NSRegularControlSize : NSSmallControlSize;
|
||||||
|
|
||||||
|
@ -362,24 +366,9 @@ static const CGFloat kCandidateTextLeftMargin = 8.0;
|
||||||
_keyLabelStripView.keyLabels = [_keyLabels subarrayWithRange:NSMakeRange(0, keyLabelCount)];
|
_keyLabelStripView.keyLabels = [_keyLabels subarrayWithRange:NSMakeRange(0, keyLabelCount)];
|
||||||
_keyLabelStripView.labelOffsetY = (keyLabelFontSize >= candidateFontSize) ? 0.0 : floor((candidateFontSize - keyLabelFontSize) / 2.0);
|
_keyLabelStripView.labelOffsetY = (keyLabelFontSize >= candidateFontSize) ? 0.0 : floor((candidateFontSize - keyLabelFontSize) / 2.0);
|
||||||
|
|
||||||
CGFloat rowHeight = fontSize;
|
CGFloat rowHeight = ceil(fontSize * 1.20);
|
||||||
|
|
||||||
if (fontSize <= 16.0) {
|
|
||||||
rowHeight += 4.0;
|
|
||||||
}
|
|
||||||
else if (fontSize <= 24.0) {
|
|
||||||
rowHeight += 8.0;
|
|
||||||
}
|
|
||||||
else if (fontSize <= 64.0) {
|
|
||||||
rowHeight += 16.0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rowHeight += 24.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[_tableView setRowHeight:rowHeight];
|
[_tableView setRowHeight:rowHeight];
|
||||||
|
|
||||||
|
|
||||||
CGFloat rowSpacing = [_tableView intercellSpacing].height;
|
CGFloat rowSpacing = [_tableView intercellSpacing].height;
|
||||||
CGFloat stripWidth = ceil(keyLabelFontSize * 1.20);
|
CGFloat stripWidth = ceil(keyLabelFontSize * 1.20);
|
||||||
CGFloat tableViewStartWidth = ceil(_maxCandidateAttrStringWidth + scrollerWidth);;
|
CGFloat tableViewStartWidth = ceil(_maxCandidateAttrStringWidth + scrollerWidth);;
|
||||||
|
@ -387,7 +376,6 @@ static const CGFloat kCandidateTextLeftMargin = 8.0;
|
||||||
CGFloat windowHeight = keyLabelCount * (rowHeight + rowSpacing);
|
CGFloat windowHeight = keyLabelCount * (rowHeight + rowSpacing);
|
||||||
|
|
||||||
NSRect frameRect = [[self window] frame];
|
NSRect frameRect = [[self window] frame];
|
||||||
frameRect = [[self window] frame];
|
|
||||||
NSPoint topLeftPoint = NSMakePoint(frameRect.origin.x, frameRect.origin.y + frameRect.size.height);
|
NSPoint topLeftPoint = NSMakePoint(frameRect.origin.x, frameRect.origin.y + frameRect.size.height);
|
||||||
|
|
||||||
frameRect.size = NSMakeSize(windowWidth, windowHeight);
|
frameRect.size = NSMakeSize(windowWidth, windowHeight);
|
||||||
|
|
Loading…
Reference in New Issue