domingo, fevereiro 27, 2011

Corrida das Árvores

Duas palavras para definir esta prova da Corrida das Árvores: belíssima e duríssima. Bela porque é dentro do parque do Monsanto, sempre rodeados pela natureza o que deu um grande jeito devido ao calor tínhamos árvores para fazer sombra, dura porque era um sobe e desce constante.

O tempo não foi brilhante 47m34s, mas também dada a dureza da prova e o facto de a ter encarado como preparação para os 20km da corrida de Cascais que vai acontecer já no próximo 6 de Março, não se pode dizer que tenha sido uma desilusão total.

Dados da minha prova:
  • Tempo de prova: 47m34s
  • Média por cada km: 4m45s
  • Velocidade média: 12,6 km/h
  • Média de 164 batimentos cardíacos por minuto
  • Máximo de 175 batimentos cardíacos por minutos
Tempos de passagem:
  • 9m29s aos 2km
  • 17m54s aos 4km
  • 27m54s aos 6km
  • Não vi a placa dos 8km

quinta-feira, fevereiro 17, 2011

Licenciados desempregados

Este post surge da sequência do que li neste blog e do que vi na reportagem "Geração à rasca" que deu ontem no jornal da noite da SIC. Felizmente para mim não me revejo nos jovem que foram apresentados na reportagem, tenho um emprego estável, comecei a trabalhar antes de acabar o curso, foi-me concedido crédito habitação e todos os meses recebo pelo menos um contacto com propostas de trabalho.

A única coisa naquela reportagem ao qual me consegui colar foi o discurso do presidente do IST em que dizia que todos os alunos do IST tinham empregabilidade garantida, e que se formassem mais o mercado absorvia porque há muitas necessidades na área da engenharia tecnológica. Apesar de me ter formado no ISEL este discurso assenta-me que nem uma luva, todos os meus colegas que terminaram o curso tiveram entrada fácil do mercado de trabalho e não sofrem dos problemas da "Geração à rasca".

Mas nada acontece por acaso, na altura em que estudava entravam todos os anos 150 novos alunos e por ano terminavam o curso 20-25 alunos. O que acontecia aos restantes? Uma pequena parte fazia só o bacharelato, mas a esmagadora maioria desistia do curso menos de 1 ano depois de começar, acabando por ir para cursos mais fáceis de concluir.

Numa sociedade cada vez mais competitiva ter curso superior de "armas medievais" ou "comunicação por sinais de fumo", nos quais se consegue entra com médias negativas, é normal que não dê garantias nenhumas de emprego, porque licenciados hoje em dia há centenas de milhar.

terça-feira, fevereiro 15, 2011

E a saga continua...

Depois do meu último post, e como em alguns casos até sou um bom samaritano, sugeri à minha gestora a utilização de um issue tracker para lhe facilitar a vida. A resposta foi algo do género:

- Já andei a analisar algumas mas não sei bem o que utilizar, mas eu costumo utilizar uma folha de excel partilhada na rede, acho que é uma boa solução,dá para por lá as tarefas e vocês irem actualizando.


Folha de excel...ai a minha vida...voltei ao jurássico e estou a ser gerido por um dinossauro.

sexta-feira, fevereiro 11, 2011

O meu caderno de anotações

Uma das coisas que não dispenso de todo quando estou a trabalhar é ter um caderno ou pelo menos umas folhas onde eu possa ir rabiscando e escrevendo coisas que não me quero esquecer. No fundo o meu caderno é o meu "diário de bordo". E tal como um diário eu considero-o como algo privado, que não quero que seja cuscado por pessoas que são puramente colegas de trabalho e para mim não têm o estatuto de amigas mas apenas de conhecidas.

Um dia desta semana quando a gestora do projecto onde estou, me passou uma série de tarefas, conforme ela estava a passar as tarefas eu estava a aponta-las, juntamente com algumas notas que me pareciam relevantes para depois as executar. Depois conforme estava a executar as tarefas punha um certo para eu próprio saber que já estava e ir controlando tudo o que precisava de fazer.

Houve uma altura que a gestora veio à minha mesa, pegou no caderno e começou a ver, para ver o que já tinha feito. Fiquei logo a olhar de lado porque considero um abuso mas pronto não vou entrar em conflito. Passado um bocado saí da minha mesa e quando voltei lá estava ela outra vez especada a olhar para o meu caderno. Chego à mesa como é óbvio todo lixado, fecho o caderno e pergunto-lhe se ela queria alguma coisa. E penso para mim, bolas se queres controlar o estado das coisas usa um issue tracker como qualquer gestor de projecto digno desse nome, mas não andes a invadir a minha privacidade.

Solução que arranjei, vou começar a escrever as coisas em folhas aleatórias, quando estou na mesa deixo o caderno entre mim e a parede, quando não estou na mesa deixo o caderno fechado.

quinta-feira, fevereiro 10, 2011

DataGrid WPF forçar Refresh

A minha tortura com as DataGrid do WPF continua. Agora o meu problema é que eu queria depois de adicionar uma linha, trabalhar os dados que estão binded com base nos valores que preenchi quando estava a adicionar a linha.

Primeiro raciocínio, devo ter um evento que me indique que a row foi adicionada, é só agarrar-me a ele e fazer o meu processamento. Aí vou eu agarrar-me ao evento RowEditEnding e faço o código que queria para alterar a row adicionada , fazendo o Refresh dos Items no fim. Executo o código e pimba estou a levar com uma excepção: " 'Refresh' não é permitido durante uma transacção AddNew ou EditItem ".

Depois de pesquisar um bocado, a solução mirabolante é desregistar o evento, fazer Commit da DataGrid, fazer o processamento que quero, forçar o Refresh e finalmente voltar a registar o evento.
private void MyRowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
{
   dGrid.RowEditEnding -= MyRowEditEnding;
   dGrid.CommitEdit();

   //O meu processamento à lista que está binded
          
   dGrid.Items.Refresh();
   dGrid.RowEditEnding += MyRowEditEnding;
}

terça-feira, fevereiro 01, 2011

Personalizar uma Row numa DataGrid WPF

Uma das coisas que mais me irrita fazer é a Graphical User Interface (GUI), perde-se imenso tempo com detalhes da treta e acabamos por não aprender nada de novo. Isto alcança o seu auge quando falamos de DataGrid, vendido como sendo a melhor coisa do mundo, a verdade é que é muito bom sim para demos rápidas, agora quando se quer começar a personalizar começa a dar mais trabalho que benefícios.

Estava aqui a trabalhar numa DataGrid em WPF quando me foi pedido que a cor de cada row fosse condicionada a uma propriedade do objecto que estava a ser bind. Parece simples...pois não é nada trivial e perdi à volta de 3h em pesquisas na internet e a implementar vários exemplos até que cheguei a uma solução que me agradou minimamente e era funcional.

Para o exemplo vamos considerar os seguintes pontos:
  • A nossa DataGrid tem o nome de dGrid;
  • O tipo do objecto que é bind a cada row é Register;
  • A propriedade do objecto que vai ser usada para condicionar a cor da row é a propriedade LK;
Os 2 principais contratempos que tive foram a altura em que podia afectar a cor da row e o facto de não poder afectar a cor da row, mas sim das células pois a cor das células sobrepõe-se à cor da row. Em relação à altura em que podia afectar a cor das células, em WPF só temos garantia que todos os filhos da janela estão prontos no evento Loaded da janela, logo tenho de ter um listener neste evento que no meu caso é o método WindowLoaded. Seguindo todos estes pressupostos o código seguinte exemplifica a solução a que cheguei.

private void WindowLoaded(object sender, RoutedEventArgs e){
    UpdateRowColor();
}

private void UpdateRowColor(){
    for (int i = 0; i < dGrid.Items.Count; ++i){
        DataGridRow row = GetRow(dGrid, i);

        if (row.Item is Register){
            Register registry = (Register)row.Item;

            for (int j = 0; j < dGrid.Columns.Count; ++j){
                if (registry.LK == "O")
                    GetCell(dGrid, row, j).Background = Brushes.Green;
                else
                    GetCell(dGrid, row, j).Background = Brushes.Red;
            }
        }
    }
}

private DataGridRow GetRow(DataGrid dataGrid, int index){
    DataGridRow row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(index);
    if (row == null){
        dataGrid.ScrollIntoView(dataGrid.Items[index]);
        dataGrid.UpdateLayout();
        row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(index);
    }
    return row;
}

private DataGridCell GetCell(DataGrid dataGrid, DataGridRow rowContainer, int column)
{
    if (rowContainer != null){
        DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer);

        // try to get the cell but it may possibly be virtualized
        DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column);
        if (cell == null){
            // now try to bring into view and retreive the cell
            dataGrid.ScrollIntoView(rowContainer, dataGrid.Columns[column]);
            cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column);
        }
        return cell;
    }
    return null;
}

private T GetVisualChild<T>(Visual parent) where T : Visual{
    T child = default(T);
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); ++i){
        Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
        child = v as T;
        if (child == null)
            child = GetVisualChild<T>(v);
        if (child != null)
            break;
    }
    return child;
}