2013-01-20 11 views
7

Ho cercato in giro su come eseguire questo, ma non riesco a trovare alcuna risposta.
Mi piacerebbe sapere se il mio NSTextfield sta già troncando il testo (... alla fine) senza dover controllare la lunghezza del suo stringValue. Devo fare questo per sapere se dovrei impostare un suggerimento sul mio NSTextfield (che agisce come una semplice etichetta).
Il motivo per cui non desidero controllare la lunghezza del campo di testo stringValue è perché ci sono alcuni caratteri che occupano più spazio di altri, quindi non è molto preciso
Grazie!Come verificare se NSTextfield sta già troncando il testo (... alla fine)

risposta

4

La soluzione migliore potrebbe essere quella di utilizzare uno NSTextView anziché uno NSTextField. Se si utilizza uno NSTextView, è possibile ottenere lo NSTextContainer dello NSTextView utilizzando la proprietà textContainer. Il contenitore può dirti il ​​containerSize (lo spazio in cui viene disegnato il testo).

NSString oggetti rispondono al metodo sizeWithAttributes:. È possibile utilizzare la struttura risultante NSSize per acquisire la larghezza del testo se disegnata con gli attributi specificati. Vedere la sezione "Costanti" del NSAttributedString Application Kit Additions Reference per capire quali attributi sono rilevanti.

Se la larghezza dello containerSize è inferiore alla larghezza dello sizeWithAttributes:, il testo verrà troncato.

EDIT: Scuse, questo è vero solo senza lineFragmentPadding, ma il default lineFragmentPadding è diverso da zero. Sottrarre textContainer.lineFragmentPadding da containerSize.width o utilizzare il metodo NSTextContainer per impostarlo su 0.

Immagino che si potrebbe anche fare alcune ipotesi circa l'area di testo in relazione alla dimensione del NSTextField e utilizzare il metodo sizeWithAttributes:NSString in concomitanza con quello, ma che non è così pulito.

EDIT 2: Mi sono reso conto che non mi sono occupato dell'interesse dell'OP nel troncare il testo usando le ellissi. Il codice di esempio seguente utilizza il troncamento in NSTextView. Ho anche pensato che potrei inserire un codice che rende ilun po 'più simile all'aspetto allo NSTextField inserendolo in uno NSBox. Aggiungere un controllo per le dimensioni per determinare se una descrizione del comando dovrebbe essere visualizzata sarebbe una semplice aggiunta al codice sottostante utilizzando le informazioni già menzionate sopra.

NSString* string = @"Hello World."; 

// get the size the text will take up using the default font 
NSSize textBounds = [string sizeWithAttributes:@{}]; 

// Create a border view that looks more or less like the border used around 
// text fields 
NSBox* borderView = [[NSBox alloc] initWithFrame:NSMakeRect(10, 10, 60, textBounds.height+4)]; 
[borderView setBoxType:NSBoxCustom]; 
[borderView setBorderType:NSBezelBorder]; 
[borderView setContentViewMargins:NSMakeSize(0, 0)]; 
[borderView setFillColor:[NSColor whiteColor]]; 

// Create the text view 
NSTextView* textView = [[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, 60, textBounds.height)]; 
[textView setTextContainerInset:NSMakeSize(2, 0)]; 
[textView.textContainer setLineFragmentPadding:0]; 
[textView setEditable:YES]; 

// Set the default paragraph style so the text is truncated rather than 
// wrapped 
NSMutableParagraphStyle* parStyle = [[NSMutableParagraphStyle alloc] init]; 
[parStyle setLineBreakMode:NSLineBreakByTruncatingTail]; 

// Do not let text get squashed to fit 
[parStyle setTighteningFactorForTruncation:0.0]; 

[textView setDefaultParagraphStyle:parStyle]; 
[parStyle release]; 

// Set text 
[textView setString:string]; 

// add NSTextView to border view 
[borderView addSubview:textView]; 
[textView release]; 

// add NSBox to view you want text view displayed in 
[self addSubview:borderView]; 
[borderView release]; 
+0

Ricordare che NSTextField ridurrà leggermente il testo se è vicino al montaggio senza troncare. [Entrambi questi campi di testo hanno lo stesso carattere di dimensione.] (Http://i.stack.imgur.com/wrJtj.png) –

+1

@JohnSauer Buon punto. Questo in realtà si verifica anche per NSTextViews. È il comportamento predefinito dell'algoritmo di troncamento per tentare di spostare i caratteri più vicini prima di troncare. Nella mia seconda modifica, impedisco che ciò accada usando il metodo 'setTighteningFactorForTruncation:' della classe 'NSMutableParagraphStyle'. – Mathew

+0

grazie per la tua risposta, ci proverò appena possibile e ti farò sapere –

0

Penso che si possa fare guardando il frame dell'editor di campo del campo di testo. Controllarne l'ampiezza in controlTextDidBeginEditing e poi di nuovo in controlTextDidEndEditing. Se quest'ultimo valore è maggiore, il testo è stato troncato. Di seguito è implementato in delegato del campo di testo (ho creato un Ivar per initialWidth):

- (void)controlTextDidBeginEditing:(NSNotification *)aNotification { 
    if (! initialWidth) 
     initialWidth = ((NSTextView *)aNotification.userInfo[@"NSFieldEditor"]).frame.size.width; 
} 


- (void)controlTextDidEndEditing:(NSNotification *)aNotification { 
    if (initialWidth) { //Make sure that beginEditing is called first 
     NSInteger finalWidth = ((NSTextView *)aNotification.userInfo[@"NSFieldEditor"]).frame.size.width; 
     if (finalWidth - initialWidth > 1) NSLog(@"We have truncation"); 
     NSLog(@"Final: %ld Initial: %ld", finalWidth,initialWidth); 
    } 
} 

Questo sembra funzionare la maggior parte del tempo, tra cui se si digita di una lunga serie, quindi eliminare fino a quando si inserisce di nuovo. In alcuni casi, mi ha dato il messaggio di registro quando ero un carattere oltre la fine del campo di testo, ma non ho ricevuto i puntini di sospensione quando la modifica è terminata.

9

Per i visitatori futuri, è possibile utilizzare il metodo -[NSCell expansionFrameWithFrame:inView:] per determinare se il troncamento è in corso.Nell'intestazione:

permette alla cellula di restituire un telaio di cella espansione se cellFrame è troppo piccolo per l'intero contenuto nella vista. ... <snip> ... Se il frame non è troppo piccolo, restituire un rettangolo vuoto e nessuna vista di punta dello strumento di espansione sarà visualizzata. Per impostazione predefinita, NSCell restituisce NSZeroRect, mentre alcune sottoclassi (come NSTextFieldCell) restituiscono il frame corretto quando richiesto.

In breve, si può dire se un NSTextField è troncando così:

NSRect expansionRect = [[self cell] expansionFrameWithFrame: self.frame inView: self]; 
    BOOL truncating = !NSEqualRects(NSZeroRect, expansionRect); 
+2

questa è la soluzione migliore – jimwan

+0

Potresti fornire una soluzione Swift 3? Non ero in grado di adattare il codice Obj-C. – ixany

-1

Swift 4 soluzione utilizzando ipmcc come base di

Sarà ridimensionare uno per uno fino a che non si adattano o fontsize = 3

var size_not_ok = true 

var conter = 0 
let mininum_font_size = 3 // will resize ultil 3 
while size_not_ok || conter < 15 { // will try 15 times maximun 
    let expansionRect = le_nstextfield.expansionFrame(withFrame: le_nstextfield.frame) 

    let truncated = !NSEqualRects(NSRect.zero, expansionRect) 

    if truncated { 

     if let actual_font_size : CGFloat = le_nstextfield.font?.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.size) as? CGFloat { 

      le_nstextfield.font = NSFont.systemFont(ofSize: actual_font_size - 1) 

      if actual_font_size < mininum_font_size { 
       break 
      } 
     } 
    } else {   
     size_not_ok = false 
    } 
    conter = conter + 1 
} 
Problemi correlati