DiffView.coffee 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. define [
  2. "ace/ace"
  3. "ace/mode/latex"
  4. "ace/range"
  5. "libs/backbone"
  6. ], (Ace, LatexMode, Range)->
  7. DiffView = Backbone.View.extend
  8. initialize: () ->
  9. @model.on "change:diff", () => @render()
  10. @render()
  11. render: ->
  12. diff = @model.get("diff")
  13. return unless diff?
  14. @createAceEditor()
  15. @aceEditor.setValue(@getPlainDiffContent())
  16. @aceEditor.clearSelection()
  17. session = @aceEditor.getSession()
  18. session.setMode(new LatexMode.Mode())
  19. session.setUseWrapMode(true)
  20. @insertMarkers()
  21. return @
  22. createAceEditor: () ->
  23. @$el.empty()
  24. $editor = $("<div/>")
  25. @$el.append($editor)
  26. @aceEditor = Ace.edit($editor[0])
  27. @aceEditor.setTheme("ace/theme/#{window.userSettings.theme}")
  28. @aceEditor.setReadOnly true
  29. @aceEditor.setShowPrintMargin(false)
  30. @aceEditor.on "mousemove", (e) =>
  31. position = @aceEditor.renderer.screenToTextCoordinates(e.clientX, e.clientY)
  32. e.position = position
  33. @updateVisibleNames(e)
  34. getPlainDiffContent: () ->
  35. content = ""
  36. for entry in @model.get("diff") or []
  37. content += entry.u or entry.i or entry.d or ""
  38. return content
  39. insertMarkers: () ->
  40. row = 0
  41. column = 0
  42. for entry, i in @model.get("diff") or []
  43. content = entry.u or entry.i or entry.d
  44. content ||= ""
  45. lines = content.split("\n")
  46. startRow = row
  47. startColumn = column
  48. if lines.length > 1
  49. endRow = startRow + lines.length - 1
  50. endColumn = lines[lines.length - 1].length
  51. else
  52. endRow = startRow
  53. endColumn = startColumn + lines[0].length
  54. row = endRow
  55. column = endColumn
  56. range = new Range.Range(
  57. startRow, startColumn, endRow, endColumn
  58. )
  59. @addMarker(range, "change-marker-#{i}", entry)
  60. addMarker: (range, id, entry) ->
  61. session = @aceEditor.getSession()
  62. markerBackLayer = @aceEditor.renderer.$markerBack
  63. markerFrontLayer = @aceEditor.renderer.$markerFront
  64. lineHeight = @aceEditor.renderer.lineHeight
  65. if entry.i? or entry.d?
  66. hue = entry.meta.user.hue()
  67. if entry.i?
  68. @_addMarkerWithCustomStyle session, markerBackLayer, range, "deleted-change-background", false, """
  69. background-color : hsl(#{hue}, 70%, 85%);
  70. """
  71. tag = "Added by #{entry.meta.user.name()}"
  72. if entry.d?
  73. @_addMarkerWithCustomStyle session, markerBackLayer, range, "deleted-change-background", false, """
  74. background-color : hsl(#{hue}, 70%, 95%);
  75. """
  76. @_addMarkerWithCustomStyle session, markerBackLayer, range, "deleted-change-foreground", true, """
  77. height: #{Math.round(lineHeight/2) - 1}px;
  78. border-bottom: 2px solid hsl(#{hue}, 70%, 40%);
  79. """
  80. tag = "Deleted by #{entry.meta.user.name()}"
  81. date = moment(parseInt(entry.meta.end_ts, 10)).format("Do MMM YYYY, h:mm:ss a")
  82. tag += " on #{date}"
  83. @_addNameTag session, id, range, tag, """
  84. background-color : hsl(#{hue}, 70%, 95%);
  85. """
  86. _addMarkerWithCustomStyle: (session, markerLayer, range, klass, foreground, style) ->
  87. session.addMarker range, klass, (html, range, left, top, config) ->
  88. if range.isMultiLine()
  89. markerLayer.drawTextMarker(html, range, klass, config, style)
  90. else
  91. markerLayer.drawSingleLineMarker(html, range, "#{klass} ace_start", config, 0, style)
  92. , foreground
  93. _addNameTag: (session, id, range, content, style) ->
  94. @nameMarkers ||= []
  95. @nameMarkers.push
  96. range: range
  97. id: id
  98. startRange = new Range.Range(
  99. range.start.row, range.start.column
  100. range.start.row, range.start.column + 1
  101. )
  102. session.addMarker startRange, "change-name-marker", (html, range, left, top, config) ->
  103. html.push """
  104. <div
  105. id = '#{id}'
  106. class = 'change-name-marker'
  107. style = '
  108. height: #{config.lineHeight}px;
  109. top: #{top}px;
  110. left: #{left}px;
  111. '
  112. >
  113. <div
  114. class="name" style="
  115. display: none;
  116. bottom: #{config.lineHeight + 3}px;
  117. #{style}
  118. ">#{content}</div>
  119. </div>
  120. """
  121. , true
  122. updateVisibleNames: (e) ->
  123. for marker in @nameMarkers or []
  124. if marker.range.contains(e.position.row, e.position.column)
  125. $("##{marker.id}").find(".name").show()
  126. else
  127. $("##{marker.id}").find(".name").hide()
  128. return DiffView