NSOutlineView Alterando imagem de divulgação
-
15-11-2019 - |
Pergunta
Na minha visualização de esboço, estou adicionando uma célula personalizada, para desenhar uma célula personalizada, estou me referindo ao código de exemplo, presente na documentação do Cocoa
http://www.martinkahr.com/2007/05/04/nscell-image-and-text-sample/
Quero alterar a imagem de divulgação da célula com minha imagem customizada, tentei seguir algumas coisas
- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
if([item isKindOfClass:[NSValue class]])
{
MyData *pDt = (MyData *)[item pointerValue];
if(pDt->isGroupElement())
{
[cell setImage:pGroupImage];
}
}
}
Mas isso também não está funcionando, existe outra maneira de alterar a imagem de divulgação, também como posso descobrir em WillDisplayCell se o item é expandido ou colapso, para que eu possa definir a imagem de acordo,
Este é apenas o lugar para alterar a imagem de divulgação?
Solução
Você já tem a ideia básica, mas o que precisa fazer é desenhar a imagem sozinho.Aqui está o código que eu uso:
- (void)outlineView:(NSOutlineView *)outlineView willDisplayOutlineCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item {
NSString *theImageName;
NSInteger theCellValue = [cell integerValue];
if (theCellValue==1) {
theImageName = @"PMOutlineCellOn";
} else if (theCellValue==0) {
theImageName = @"PMOutlineCellOff";
} else {
theImageName = @"PMOutlineCellMixed";
}
NSImage *theImage = [NSImage imageNamed: theImageName];
NSRect theFrame = [outlineView frameOfOutlineCellAtRow:[outlineView rowForItem: item]];
theFrame.origin.y = theFrame.origin.y +17;
// adjust theFrame here to position your image
[theImage compositeToPoint: theFrame.origin operation:NSCompositeSourceOver];
[cell setImagePosition: NSNoImage];
}
Você precisará de 3 imagens diferentes como você pode ver, uma para o ON
estado, um para o OFF
estadual e também um para o MIXED
estado que deveria estar a meio caminho entre os dois.O estado misto garante que você ainda obtenha a animação de abertura e fechamento.
Outras dicas
Depois de pesquisar esse problema e tentar algumas das respostas aqui, descobri que as outras abordagens mencionadas funcionarão, mas exigirão que você execute muito mais intervenção manual para evitar artefatos de tela e outros comportamentos estranhos.
A solução mais simples que encontrei é a seguinte, que deve funcionar na maioria dos casos.
Esta solução tem o benefício adicional de o sistema tratar automaticamente muitos outros casos, como movimentação de colunas, etc., sem o seu envolvimento.
- (void)outlineView:(NSOutlineView *)outlineView willDisplayOutlineCell:(id)cell
forTableColumn:(NSTableColumn *)tableColumn
item:(id)item
{
[cell setImage:[NSImage imageNamed: @"Navigation right 16x16 vWhite_tx"]];
[cell setAlternateImage:[NSImage imageNamed: @"Navigation down 16x16 vWhite_tx"]];
}
No seu caso, você encerraria isso com sua lógica de detecção de classe e definiria as imagens das células adequadamente para seus casos.
Uma boa maneira de alterar a imagem de divulgação é usar uma visualização de esboço baseada em visualização:
No seu ViewController com NSOutlineViewDelegate:
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
CustomNSTableCellView *cell = [outlineView makeViewWithIdentifier:tableColumn.identifier owner:self];
cell.item = item;
return cell;
}
Você precisa subclassificar seu NSOutlineView e substituir o método:
- (id)makeViewWithIdentifier:(NSString *)identifier owner:(id)owner
{
id view = [super makeViewWithIdentifier:identifier owner:owner];
if ([identifier isEqualToString:NSOutlineViewDisclosureButtonKey])
{
// Do your customization
// return disclosure button view
[view setImage:[NSImage imageNamed:@"Disclosure_Categories_Plus"]];
[view setAlternateImage:[NSImage imageNamed:@"Disclosure_Categories_Minus"]];
[view setBordered:NO];
[view setTitle:@""];
return view;
}
return view;
}
//Frame of the disclosure view
- (NSRect)frameOfOutlineCellAtRow:(NSInteger)row
{
NSRect frame = NSMakeRect(4, (row * 22), 19, 19);
return frame;
}
Para quem procura a solução Swift2.Subclasse NSRow do seu Outlineview e substitua o método didAddSubview conforme abaixo.
override func didAddSubview(subview: NSView) {
super.didAddSubview(subview)
if let sv = subview as? NSButton {
sv.image = NSImage(named:"IconNameForCollapsedState")
sv.alternateImage = NSImage(named:"IconNameForExpandedState")
}
}
Isso é o que tentei e trabalhei até agora,
/* porque estamos mostrando nosso próprio botão de divulgação e expansão */
- (NSRect)frameOfOutlineCellAtRow:(NSInteger)row {
return NSZeroRect;
}
- (NSRect)frameOfCellAtColumn:(NSInteger)column row:(NSInteger)row {
NSRect superFrame = [super frameOfCellAtColumn:column row:row];
if ((column == 0) && ([self isGroupItem:[self itemAtRow:row]])) {
return NSMakeRect(0, superFrame.origin.y, [self bounds].size.width, superFrame.size.height);
}
return superFrame;
}
Eu subclassifiquei a classe NSOutlineView e substituí esses métodos,
[self isGroupItem] é para verificar se é grupo ou não.mas tenho um problema, agora parece que preciso fazer o manuseio do mouse :(, ao clicar duas vezes a linha do grupo não está alternando