2009-11-18 16 views
9

Tengo un NSTextFieldCell que deseo mostrar con alineación vertical media. Gracias a una pregunta anterior aquí y una entrada de blog, tengo dos soluciones de trabajo.alineación vertical NSTextFieldCell, las soluciones parecen aplastar la alineación horizontal

Sin embargo, ambas soluciones parecen aplastar mi capacidad de configurar la celda como alineado a la derecha. ¿Alguien puede ayudarme a hacer que cualquiera de estas soluciones sea compatible con ambas formas de alineación?

Este es el código para una solución:

@implementation MiddleAlignedTextFieldCell 

- (NSRect)titleRectForBounds:(NSRect)theRect { 
    NSRect titleFrame = [super titleRectForBounds:theRect]; 
    NSSize titleSize = [[self attributedStringValue] size]; 
    titleFrame.origin.y = theRect.origin.y - .5 + (theRect.size.height - titleSize.height)/2.0; 
    return titleFrame; 
} 

- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { 
    NSRect titleRect = [self titleRectForBounds:cellFrame]; 
    [[self attributedStringValue] drawInRect:titleRect]; 
} 

@end 

La solución alternativa es (obtenido de this blog):

@implementation RSVerticallyCenteredTextFieldCell 

- (NSRect)drawingRectForBounds:(NSRect)theRect 
{ 
    NSRect newRect = [super drawingRectForBounds:theRect]; 

    if (mIsEditingOrSelecting == NO) 
    { 
     // Get our ideal size for current text 
     NSSize textSize = [self cellSizeForBounds:theRect]; 

     // Center that in the proposed rect 
     float heightDelta = newRect.size.height - textSize.height; 
     if (heightDelta > 0) 
     { 
      newRect.size.height -= heightDelta; 
      newRect.origin.y += (heightDelta/2); 
     } 
    } 

    return newRect; 
} 

- (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject start:(int)selStart length:(int)selLength 
{ 
    aRect = [self drawingRectForBounds:aRect]; 
    mIsEditingOrSelecting = YES;  
    [super selectWithFrame:aRect inView:controlView editor:textObj delegate:anObject start:selStart length:selLength]; 
    mIsEditingOrSelecting = NO; 
} 

- (void)editWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject event:(NSEvent *)theEvent 
{ 
    aRect = [self drawingRectForBounds:aRect]; 
    mIsEditingOrSelecting = YES; 
    [super editWithFrame:aRect inView:controlView editor:textObj delegate:anObject event:theEvent]; 
    mIsEditingOrSelecting = NO; 
} 

@end 

Respuesta

5

Estoy publicando esta respuesta a la pregunta, ya que funciona, sin embargo, me parece muy molesto el hecho de que no pude encontrar otra manera de verificar la configuración de alineación de IB. Acceder a _cFlags parece un poco sucio, y me encantaría encontrar un método más limpio.

Basado en el código publicado anteriormente en this blog entry.

- (NSRect)drawingRectForBounds:(NSRect)theRect 
{ 
    // Get the parent's idea of where we should draw 
    NSRect newRect = [super drawingRectForBounds:theRect]; 

    if (mIsEditingOrSelecting == NO) 
    { 
     // Get our ideal size for current text 
     NSSize textSize = [self cellSizeForBounds:theRect]; 

     // Center that in the proposed rect 
     float heightDelta = newRect.size.height - textSize.height; 
     if (heightDelta > 0) 
     { 
      newRect.size.height -= heightDelta; 
      newRect.origin.y += (heightDelta/2); 
     } 

     // For some reason right aligned text doesn't work. This section makes it work if set in IB. 
     // HACK: using _cFlags isn't a great idea, but I couldn't find another way to find the alignment. 
     // TODO: replace _cFlags usage if a better solution is found. 
     float widthDelta = newRect.size.width - textSize.width; 
     if (_cFlags.alignment == NSRightTextAlignment && widthDelta > 0) { 
      newRect.size.width -= widthDelta; 
      newRect.origin.x += widthDelta; 
     } 

    } 

    return newRect; 
} 
3

Usted puede utilizar NSParagraphStyle/NSMutableParagraphStyle para establecer la alineación (y otros atributos) Agregue un objeto NSParagraphStyle configurado apropiadamente al rango completo de su cadena atribuida.

+0

Eso requiere que me una en esa parte de la presentación con mi capa de datos, y sinceramente, no estoy seguro de que me guste. Esto debería respetar las opciones presentadas en IB, pero por alguna razón no (para ese asunto, la alineación vertical también debería ser una opción en IB). –

+0

No estoy seguro de cómo se está mezclando más que establecer la cadena de NSTextFieldCell en algo de su capa de modelo.:-) La alineación (y la fuente, y el color, y el tamaño, ...) es parte de todo esto. Estoy de acuerdo, sin embargo, en que la alineación vertical debe ser una opción: presentar un informe de mejora. Como no está disponible, tendrá que contabilizarlo en el código de dibujo. –

+0

Er, eso es "solicitud de mejora". Enlace: http://bugreporter.apple.com –

2

Hay un par de posibles soluciones publicadas en un similar question que pedí hace un tiempo.

En honor a la verdad, que todavía utilizan los indocumentados _cFlags.vCentered booleano (tsk tsk , mal programador!) Para hacer el trabajo. Es simple, y funciona. Reinventaré la rueda más adelante si es necesario.

actualización:

bien, creo que he descubierto. Ambas soluciones se basan en una llamada al super para obtener el rect predeterminado, y luego modifican origin.y y size.height para realizar el centrado vertical. Las llamadas al super, sin embargo, devuelven un rectángulo cuyo ancho ya se ha ajustado para ajustarse al texto horizontalmente.

La solución es utilizar origin.x y size.width de los límites rect que se pasa en el método:

En la solución # 1:

- (NSRect)titleRectForBounds:(NSRect)theRect { 
    NSRect titleFrame = [super titleRectForBounds:theRect]; 
    NSSize titleSize = [[self attributedStringValue] size]; 

    // modified: 
    theRect.origin.y += (theRect.size.height - titleSize.height)/2.0 - 0.5; 
    return theRect; 
} 

En la solución # 2 :

- (NSRect)drawingRectForBounds:(NSRect)theRect 
{ 
    NSRect newRect = [super drawingRectForBounds:theRect]; 

    // modified: 
    newRect.origin.x = theRect.origin.x; 
    newRect.size.width = theRect.size.width; 

    if (mIsEditingOrSelecting == NO) 
    { 
     // Get our ideal size for current text 
     NSSize textSize = [self cellSizeForBounds:theRect]; 

     // Center that in the proposed rect 
     float heightDelta = newRect.size.height - textSize.height; 
     if (heightDelta > 0) 
     { 
      newRect.size.height -= heightDelta; 
      newRect.origin.y += (heightDelta/2); 
     } 
    } 

    return newRect; 
} 
+0

En realidad, fue la solución a esa pregunta que encontré una de mis soluciones. –

+0

Estoy tratando de averiguar cómo mantener la alineación horizontal con esta solución. Pero puedo tener que bajar y probar otra ruta si no puedo. –

+0

Me sorprende que la alineación horizontal se vea afectada por ninguna de estas soluciones, ya que ninguna de ellas entra en conflicto con la dimensión x. ¿Cómo estás configurando la alineación? –

Cuestiones relacionadas